From 09b583fdb2eacf3cc7bcd3d37b4fea8589f1b9b0 Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Fri, 8 Feb 2008 18:23:13 +0100 Subject: [PATCH] push a18c97e3310ae68c9cf1d09430f25ca292f320eb --- ANNOUNCE | 791 +++++++-------- ChangeLog | 1083 +++++++++++++++++++++ VERSION | 2 +- configure | 76 +- configure.ac | 1 + dlls/advapi32/service.c | 4 +- dlls/advapi32/tests/security.c | 4 +- dlls/advapi32/tests/service.c | 3 +- dlls/atl/atl_ax.c | 3 +- dlls/cabinet/tests/fdi.c | 73 +- dlls/comctl32/animate.c | 63 +- dlls/comctl32/comboex.c | 74 +- dlls/comctl32/listview.c | 2 +- dlls/comctl32/monthcal.c | 2 +- dlls/comctl32/pager.c | 5 +- dlls/comctl32/propsheet.c | 15 +- dlls/comctl32/rebar.c | 75 +- dlls/comctl32/status.c | 8 +- dlls/comctl32/tab.c | 70 +- dlls/comctl32/tests/comboex.c | 24 +- dlls/comctl32/tests/datetime.c | 18 +- dlls/comctl32/tests/header.c | 22 +- dlls/comctl32/tests/listview.c | 15 +- dlls/comctl32/tests/monthcal.c | 21 +- dlls/comctl32/tests/progress.c | 14 +- dlls/comctl32/tests/rebar.c | 14 +- dlls/comctl32/tests/treeview.c | 15 +- dlls/comctl32/toolbar.c | 19 +- dlls/comctl32/trackbar.c | 8 +- dlls/comctl32/treeview.c | 8 +- dlls/crypt32/decode.c | 3 + dlls/crypt32/encode.c | 3 + dlls/d3d9/d3d9_private.h | 1 + dlls/d3d9/device.c | 43 +- dlls/d3d9/tests/device.c | 109 ++- dlls/d3d9/tests/visual.c | 222 ++++- dlls/d3dx8/d3dx8_main.c | 4 +- dlls/d3dx8/math.c | 2 +- dlls/dbghelp/Makefile.in | 1 + dlls/dbghelp/dbghelp_private.h | 16 +- dlls/dbghelp/dwarf.c | 62 +- dlls/dbghelp/minidump.c | 84 +- dlls/dbghelp/msc.c | 133 ++- dlls/dbghelp/stabs.c | 6 +- dlls/dbghelp/symbol.c | 48 +- dlls/dbghelp/type.c | 30 +- dlls/ddraw/tests/d3d.c | 16 +- dlls/ddraw/tests/ddrawmodes.c | 6 +- dlls/ddraw/tests/visual.c | 40 +- dlls/gdi32/bitmap.c | 70 +- dlls/gdi32/brush.c | 22 +- dlls/gdi32/dc.c | 34 - dlls/gdi32/dib.c | 16 +- dlls/gdi32/font.c | 122 +-- dlls/gdi32/freetype.c | 144 ++- dlls/gdi32/gdi32.spec | 4 +- dlls/gdi32/gdi_private.h | 3 - dlls/gdi32/gdiobj.c | 41 +- dlls/gdi32/palette.c | 39 +- dlls/gdi32/pen.c | 24 +- dlls/gdi32/printdrv.c | 22 + dlls/gdi32/tests/bitmap.c | 12 +- dlls/gdiplus/gdiplus.spec | 4 +- dlls/gdiplus/pen.c | 10 + dlls/gdiplus/stringformat.c | 10 + dlls/gdiplus/tests/graphicspath.c | 2 +- dlls/hlink/extserv.c | 5 +- dlls/hlink/hlink.spec | 4 +- dlls/hlink/hlink_main.c | 109 ++- dlls/hlink/tests/hlink.c | 462 ++++++++- dlls/itss/tests/protocol.c | 4 + dlls/kernel32/kernel32.spec | 1 + dlls/kernel32/locale.c | 6 +- dlls/kernel32/ne_module.c | 5 +- dlls/kernel32/path.c | 16 +- dlls/kernel32/process.c | 11 + dlls/kernel32/tests/actctx.c | 3 +- dlls/kernel32/tests/toolhelp.c | 5 +- dlls/kernel32/tests/version.c | 15 +- dlls/localspl/localspl_main.c | 633 +++++++++++- dlls/mapi32/mapi32.spec | 2 +- dlls/mapi32/util.c | 12 + dlls/mshtml/Makefile.in | 2 +- dlls/mshtml/mshtml_private.h | 14 + dlls/mshtml/nsio.c | 27 +- dlls/mshtml/tests/protocol.c | 159 +-- dlls/msi/action.c | 24 + dlls/msi/database.c | 4 + dlls/msi/format.c | 1822 ++++++++++++++++++++--------------- dlls/msi/msi.c | 51 +- dlls/msi/streams.c | 89 +- dlls/msi/tests/Makefile.in | 2 +- dlls/msi/tests/db.c | 450 +++++++++ dlls/msi/tests/format.c | 403 +++++--- dlls/msi/tests/install.c | 61 ++ dlls/msi/tests/msi.c | 254 +++++ dlls/msvcrt/msvcrt.spec | 2 + dlls/msvfw32/drawdib.c | 2 + dlls/msxml3/element.c | 9 +- dlls/msxml3/tests/domdoc.c | 7 +- dlls/msxml3/tests/xmldoc.c | 4 +- dlls/msxml3/xmldoc.c | 3 + dlls/ntdll/file.c | 19 +- dlls/ntdll/tests/exception.c | 3 +- dlls/ntdsapi/ntdsapi.c | 5 + dlls/ntoskrnl.exe/ntoskrnl.c | 17 + dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 4 +- dlls/ole32/Makefile.in | 1 + dlls/ole32/moniker.h | 2 + dlls/ole32/ole32.spec | 2 +- dlls/ole32/oleproxy.c | 2 + dlls/ole32/pointermoniker.c | 654 +++++++++++++ dlls/ole32/regsvr.c | 3 - dlls/ole32/tests/marshal.c | 2 +- dlls/ole32/tests/moniker.c | 108 +++ dlls/oleaut32/olefont.c | 1 + dlls/oleaut32/olepicture.c | 1 + dlls/oleaut32/tests/olefont.c | 1 + dlls/oleaut32/tests/safearray.c | 34 +- dlls/oleaut32/tests/tmarshal.c | 2 + dlls/oleaut32/tmarshal.c | 1 + dlls/olecli32/olecli.h | 129 +++ dlls/olecli32/olecli16.c | 111 +-- dlls/olecli32/olecli_main.c | 111 +-- dlls/pdh/pdh_main.c | 2 +- dlls/quartz/main.c | 1 + dlls/quartz/quartz_private.h | 1 + dlls/quartz/regsvr.c | 18 + dlls/quartz/videorenderer.c | 6 + dlls/riched20/caret.c | 14 +- dlls/riched20/editor.c | 351 ++++++- dlls/riched20/editor.h | 9 +- dlls/riched20/editstr.h | 1 + dlls/riched20/list.c | 1 + dlls/riched20/paint.c | 30 +- dlls/riched20/richole.c | 214 +++- dlls/riched20/rtf.h | 1 + dlls/riched20/run.c | 36 +- dlls/riched20/tests/editor.c | 36 +- dlls/riched20/undo.c | 6 + dlls/riched20/wrap.c | 9 +- dlls/riched20/writer.c | 3 + dlls/rpcrt4/rpc_message.c | 9 +- dlls/rpcrt4/rpc_server.c | 2 + dlls/rpcrt4/tests/rpc.c | 21 +- dlls/rpcrt4/tests/server.c | 12 +- dlls/rsaenh/rsaenh.c | 7 +- dlls/secur32/dispatcher.c | 7 + dlls/secur32/ntlm.c | 259 +++-- dlls/shell32/shell32_main.c | 10 +- dlls/shell32/shfldr_unixfs.c | 2 +- dlls/shell32/systray.c | 5 +- dlls/shell32/tests/shelllink.c | 4 +- dlls/shell32/tests/shellpath.c | 3 +- dlls/shell32/tests/systray.c | 6 +- dlls/url/url.spec | 2 +- dlls/url/url_main.c | 22 + dlls/urlmon/binding.c | 340 +++++-- dlls/urlmon/http.c | 17 + dlls/urlmon/session.c | 17 + dlls/urlmon/tests/Makefile.in | 2 +- dlls/urlmon/tests/misc.c | 85 ++ dlls/urlmon/tests/protocol.c | 27 +- dlls/urlmon/tests/url.c | 271 ++++-- dlls/urlmon/umon.c | 21 + dlls/urlmon/urlmon.spec | 4 +- dlls/urlmon/urlmon_main.c | 42 + dlls/urlmon/urlmon_main.h | 1 + dlls/user32/combo.c | 9 +- dlls/user32/defwnd.c | 4 +- dlls/user32/display.drv.spec | 2 +- dlls/user32/hook.c | 2 +- dlls/user32/listbox.c | 8 +- dlls/user32/menu.c | 3 +- dlls/user32/message.c | 19 - dlls/user32/nonclient.c | 10 +- dlls/user32/painting.c | 5 +- dlls/user32/spy.c | 16 +- dlls/user32/sysparams.c | 8 +- dlls/user32/tests/cursoricon.c | 186 ++++ dlls/user32/tests/listbox.c | 14 + dlls/user32/uitools.c | 3 +- dlls/user32/user_private.h | 1 + dlls/user32/winpos.c | 3 +- dlls/uxtheme/tests/system.c | 6 +- dlls/version/info.c | 4 + dlls/version/tests/info.c | 25 + dlls/wined3d/arb_program_shader.c | 25 +- dlls/wined3d/baseshader.c | 2 + dlls/wined3d/basetexture.c | 18 +- dlls/wined3d/cubetexture.c | 9 +- dlls/wined3d/device.c | 248 +++-- dlls/wined3d/directx.c | 185 +++- dlls/wined3d/drawprim.c | 11 +- dlls/wined3d/glsl_shader.c | 20 +- dlls/wined3d/surface.c | 103 +- dlls/wined3d/surface_base.c | 5 +- dlls/wined3d/texture.c | 9 +- dlls/wined3d/vertexbuffer.c | 89 +- dlls/wined3d/volumetexture.c | 9 +- dlls/wined3d/wined3d_private.h | 10 +- dlls/winemp3.acm/interface.c | 6 +- dlls/winemp3.acm/layer2.c | 4 +- dlls/wineps.drv/driver.c | 4 +- dlls/wineps.drv/type1afm.c | 2 +- dlls/winex11.drv/bitblt.c | 10 +- dlls/winex11.drv/bitmap.c | 4 +- dlls/winex11.drv/clipboard.c | 14 +- dlls/winex11.drv/dib.c | 4 +- dlls/winex11.drv/event.c | 4 +- dlls/winex11.drv/keyboard.c | 10 +- dlls/winex11.drv/opengl.c | 39 +- dlls/winex11.drv/palette.c | 50 +- dlls/winex11.drv/winpos.c | 2 +- dlls/winex11.drv/wintab.c | 11 +- dlls/winex11.drv/x11drv.h | 4 +- dlls/winex11.drv/x11drv_main.c | 63 +- dlls/winex11.drv/xfont.c | 4 +- dlls/winex11.drv/xinerama.c | 14 +- dlls/wininet/ftp.c | 6 +- dlls/wininet/http.c | 64 +- dlls/wininet/internet.c | 18 +- dlls/wininet/tests/http.c | 40 +- dlls/wininet/urlcache.c | 8 +- dlls/wininet/utility.c | 2 +- dlls/winmm/message16.c | 24 +- dlls/winmm/winmm.c | 6 +- dlls/winspool.drv/info.c | 266 +---- dlls/winspool.drv/wspool.c | 87 ++ dlls/winspool.drv/wspool.h | 3 + dlls/wintab32/wintab32.c | 3 +- dlls/wintrust/tests/crypt.c | 23 +- dlls/wnaspi32/winaspi16.c | 2 +- dlls/ws2_32/async.c | 8 +- dlls/ws2_32/socket.c | 16 +- include/Makefile.in | 1 + include/d3dx8.h | 4 + include/d3dx8core.h | 18 +- include/d3dx8math.h | 2 +- include/{d3dx8.h => d3dx8mesh.h} | 20 +- include/gdiplusenums.h | 7 + include/hlink.idl | 2 + include/richedit.h | 2 +- include/shlobj.h | 13 +- include/urlmon.idl | 1 + include/uuids.h | 1 + include/wine/mscvpdb.h | 29 +- include/wine/test.h | 18 + include/wine/wined3d_gl.h | 3 +- include/wintrust.h | 2 + include/winuser.h | 2 +- programs/cmd/Ru.rc | 16 +- programs/explorer/systray.c | 174 ++-- programs/winecfg/libraries.c | 6 +- programs/winedbg/gdbproxy.c | 29 +- programs/wordpad/registry.c | 2 +- server/named_pipe.c | 11 +- tools/widl/client.c | 7 + tools/widl/parser.l | 6 +- tools/widl/proxy.c | 12 + tools/widl/server.c | 7 + tools/widl/typegen.c | 66 ++ tools/widl/typegen.h | 3 + tools/widl/utils.c | 3 + tools/widl/widl.c | 3 + tools/widl/write_msft.c | 5 +- tools/winapi/win32.api | 73 +- tools/wine.inf | 2 +- tools/winedump/lnk.c | 287 ++++-- tools/winedump/msc.c | 6 + 270 files changed, 10762 insertions(+), 3749 deletions(-) rewrite ANNOUNCE (94%) rewrite dlls/msi/format.c (62%) create mode 100644 dlls/ole32/pointermoniker.c create mode 100644 dlls/olecli32/olecli.h copy include/{d3dx8.h => d3dx8mesh.h} (71%) diff --git a/ANNOUNCE b/ANNOUNCE dissimilarity index 94% index cb0e5760f67..c87ab7a5ff5 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,431 +1,360 @@ -This is release 0.9.54 of Wine, a free implementation of Windows on Unix. - -What's new in this release: - - Photoshop CS/CS2 should now work, please help us testing it. - See http://wiki.winehq.org/AdobePhotoshop for details. - - A number of RPC fixes. - - Various improvements to the debugger support. - - Lots of bug fixes. - -Because of lags created by using mirrors, this message may reach you -before the release is available at the public sites. The sources will -be available from the following locations: - - http://ibiblio.org/pub/linux/system/emulators/wine/wine-0.9.54.tar.bz2 - http://prdownloads.sourceforge.net/wine/wine-0.9.54.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 or CVS -repositories. Check respectively http://www.winehq.org/site/git or -http://www.winehq.org/site/cvs for details. - -If you fix something, please submit a patch; instructions on how to do -this can be found at http://www.winehq.org/site/sending_patches - -Wine is available thanks to the work of many people. See the file -AUTHORS in the distribution for the complete list. - ----------------------------------------------------------------- - -Changes since 0.9.53: - -Alexander Dorofeyev (4): - wined3d: Change colorkey fixup for stage 0 alphaop / alphaarg. - ddraw: Fix handling of alpha with D3DTBLEND_MODULATE. - ddraw/tests: Add test for D3DTBLEND_MODULATE. - wined3d: Fix not released swapchain in some codepaths. - -Alexander Nicolaysen Sørnes (7): - wordpad: Fix width when text break = margins. - wordpad: Add basic ruler. - riched20: Include selection bar size in POSFROMCHAR. - riched20: Don't clear CFM_UNDERLINE flag when applying styles where it is set. - uninstaller: Disable Uninstall button when no items selected. - uninstaller: Fix Norwegian Bokmål resource. - winecfg: Update Norwegian Bokmål resource. - -Alexandre Julliard (55): - kernel32: Close the stdio handles when creating a detached process. - kernel32: Don't inherit stdin/stdout handles in wineboot. - user32: Don't inherit stdin/stdout handles in explorer. - server: Take into account the extended registers part of the i386 context. - kernel32/tests: Avoid size_t in traces. - ntdll: Copy extended registers too in copy_context(). - ntdll: Linux support for saving and restoring the extended FPU context on exceptions. - ntdll: Mac OS support for saving and restoring the extended FPU context on exceptions. - ntdll: Restore typecast that is really needed. - ntdll: Fall back to a server device ioctl for files with no associated fd. - mountmgr.sys: Fix values returned for IOCTL_STORAGE_GET_DEVICE_NUMBER on emulated disks. - winebuild: Reserve the space for the PE header in the .init section. - winmm: Load only one sound driver at a time. - wineboot: Add a --init option used when launched automatically at startup. - wineboot: Delay import the dlls that are not needed for the default initialisation. - winebuild: Don't try to use the .init section on Mac OS. - kernel32: Fix the system affinity returned by GetProcessAffinityMask. - server: Don't force the process affinity to 1, leave it up to the client. - winex11.drv: Don't fetch the atom for a null device type. - winex11.drv: Don't create a win_data structure for the desktop window, except in the process that owns it. - winex11.drv: Moved initialization of screen_width/height to xinerama_init to do it inside the x11 lock. - ntdll: Don't try to restore extended fpu context if not supported. - widl: Use the real argument names in the C method macros. - winex11.drv: Set the initial icon hints in set_initial_wm_hints(). - libwine: Properly increment source pointer for surrogates in wine_utf8_wcstombs. - user32,server: Set the initial window rectangles to 0,0-0,0. - winex11.drv: Fix handling of strange window sizes in CreateWindow, with tests. - winex11.drv: Only allocate wm hints if we have an X11 window. - ntdll: Don't fetch extended FPU context if there's no FPU context at all. - server: Add a separate request to set the window visible rect. - server: Invalidate the correct region when custom valid rects are specified. - winex11: Abstract the server part of SetWindowPos into a separate function. - winex11: Make the client rect relative to the parent window for consistency with the server side. - winex11: Properly invalidate moved child windows instead of forcing SWP_NOCOPYBITS. - winex11: Move the window bits according to the valid rects instead of invalidating. - winex11: Move resetting of the cursor clip rectangle into xinerama_init(). - winex11: Leave it up to explorer to specify the correct size and position for the desktop. - winex11: Update the win data rectangles before doing anything else in SetWindowPos. - winex11: Move code around in X11DRV_SetWindowPos to reduce indentation levels. - winex11: Add a mapped flag to the window data instead of relying on WS_VISIBLE. - winex11: Apply the existing window region (if any) when creating the whole window. - winex11: Set hints for the existing window text when creating the whole window. - winex11: Set icon hints on non-managed windows too, since they may become managed later on. - winex11: Get the icon from the window in case it was changed before the whole window was created. - winex11: Remove obsolete code to set Z-order for child windows. - winex11: Export a function to dock a window into the system tray, and get rid of the WS_EX_TRAYWINDOW style. - comctl32: Tooltips should be top-most windows. - user32: Menus should be top-most windows. - winex11: Don't create a win_data structure for the root window in non-desktop mode. - winex11: Create the window data structure lazily, once the window is made visible. - winex11: Check for need to make window managed when WS_VISIBLE is set outside of SetWindowPos. - winex11: Catch DIB memory accesses that touch the last page beyond the DIB bits end. - user32: Moved the bulk of CreateWindow and SetWindowPos from the driver back into user32. - Avoid sizeof in traces. - winex11: Check for managed mode in create_whole_window again now that it is called lazily. - -Alistair Leslie-Hughes (15): - msxml3: Implement get_dataType. - msxml3: Correct get_attributes for CDATA Section. - msxml3: Implemented IXMLDOMCDATASection COM Object. - msxml3: Implement GetClassID for XMLDocument IPersistStream interface. - msxml3: Corrected getAttribute to return current value and assign output var. - mscoree: Fix memory leak. - msxml3: Implement put_text. - msxml3: Implement get_nodeTypeString. - msxml3: Attribute nodes are not typed. - msxml3: Implement IXMLDOMImplementation Interface. - msxml3: Implement IXMLDOMDocumentFragment Interface. - msxml3: Entity Reference nodes do not support attributes property. - msxml3: Implement IXMLDOMEntityReference interface. - msxml3: Return correct IDispatch Interface. - gmsxml3: Added typelib support. - -Allan Tong (1): - wined3d: Set swapchain container before flagging front buffer with SFLAG_INDRAWABLE. - -Andrej Sinicyn (1): - wordpad: Update German strings and correct shortcuts to match XP wordpad. - -Andrew Talbot (30): - netapi32: Remove unneeded cast. - msvcrt: Remove unneeded casts. - ntdll: Remove unneeded casts. - msxml3: Remove unneeded cast. - msvfw32: Remove unneeded casts. - setupapi: Fix dead code (Coverity). - ole32: Remove unneeded casts. - oleaut32: Remove unneeded casts. - qcap: Remove unneeded casts. - psapi: Remove unneeded cast. - rpcrt4: Remove unneeded casts. - quartz: Remove unneeded casts. - riched20: Remove unneeded casts. - rsaenh: Remove unneeded casts. - sane.ds: Remove unneeded casts. - secur32: Remove unneeded casts. - setupapi: Remove unneeded casts. - shell32: Remove unneeded casts. - shell32: Remove unneeded casts. - shell32: Remove unneeded casts. - urlmon: Remove unneeded cast. - user32: Remove unneeded casts. - user32: Remove unneeded casts. - uxtheme: Remove unneeded casts. - vmm.vxd: Remove unneeded casts. - wined3d: Remove unneeded casts. - wined3d: Remove unneeded casts. - wined3d: Remove unneeded casts. - wined3d: Remove unneeded casts. - winedos: Remove unneeded casts. - -Andrey Esin (9): - wineboot: Russian translation. - shell32: Update Russian translation. - wordpad: Adding to Russian translation. - wordpad: Corrections in Russian translation. - regedit: Update Russian translation. - write: Russian translation. - browseui: Russian translation. - wininet: One addition to Russian translation. - credui: Added Russian translation. - -Aric Stewart (1): - wineps.drv: Properly handle NULL LPLOGFONT in PSDRV_EnumDeviceFonts. - -Austin English (4): - Misc spelling fixes. - tools: Spelling fixes. - wined3d: Spelling fixes. - comctl32: Spelling fixes. - -Christoph von Wittich (1): - msi: Fix process token leak. - -Christopher Berner (1): - user32: Fixed off by one scroll bar pixels. - -Dan Hipschman (1): - oleaut32: Use the symbolic name for TYPEFLAG_FDISPATCHABLE. - -Dan Kegel (5): - gdiplus/tests: Don't free if alloc failed. - hlink/tests: Skip tests if hlink couldn't be created. - urlmon: Fix unlikely free of uninitialized pointer. - winealsa.drv: Don't return garbage if can't find active channel. - gdi32: Fix AddFontResource behavior with relative paths. - -Dmitry Timoshkov (11): - gdi32: Use public FS_xxxxxx defines. - gdi32: Initialize more fields in GetEnumStructs. - gdi32: Add a test for undocumented EnumFontFamiliesEx(NULL), make it pass under Wine. - gdi32: Do not allow to create too large device dependent bitmaps like Windows does. - gdi32: Allocate cache for face enumeration data only when necessary. - ntdll: Do not perform base relocation if an image is not a DLL. - gdi32: Actually perform the fractional scaling test, make it pass under Wine. - winebuild: Add a couple of missing indentations in the generated asm files. - user32: Make MapVirtualKeyEx(MAPVK_VK_TO_CHAR) behave more like in Windows. - shell32: Add a LogoffWindowsDialog stub. - winex11.drv: Remove an incorrect FIXME. - -Eric Pouech (17): - dbghelp: Silence superfluous message (spotted by Robert Reif). - dbghelp: In Minidump, change a couple of internal names for consistency. - winedbg: Fixed bt all so that current process/thread isn't lost. - winedbg: Workaround broken minidumps with invalid 32->64 address conversion. - winedbg: Added a way to support differently selector information depending on current target. - ole32: Fixed datacache object so that we can retrieve meaningful information. - msvcrt: symbol undecoration: Now correctly parsing the template forms. - msvcrt: symbol undecoration: Handling of void in template parameters' list. - msvcrt: symbol undecoration: Added support for cointerface. - msvcrt: symbol undecoration: Added support for a couple of more calling conventions. - msvcrt: symbol undecoration: Corrected handling of non static member function modifiers. - msvcrt: symbol undecoration: Added support for thunks. - msvcrt: symbol undecoration: Added support for RTTI types. - msvcrt: symbol undecoration: Really check that we get a template string before making use of it. - ntdll: Fixed getting the RTS status from line, and now using sane default values for all (compilation/system) cases. - msvcrt: Corrected the .spec definition for the printf functions family. - regedit: Warn about newest unicode export from native regedit. - -Eric van Beurden (6): - dbghelp: Update some mscvpdb.h definitions and descriptions. - dbghelp: Return TRUE in SymInitializeW if process is already initialized and add an ERR to SymCleanup. - dbghelp: Wrap TRACE strings using the debugstr functions and update some type casting. - dbghelp: Some minidump corrections so that windbg can read our minidump files. - dbghelp: Fix file searching to search only listed directories instead of the whole HD. - dbghelp: Prevent huge minidumps by ensuring the memory range is clamped. - -Francois Gouget (11): - gdi32: Small wording tweaks in comments. - ddraw/tests: Fix compilation on systems that don't support nameless unions. - Fix spelling error in the generated conformance test files. - include: Document some Microsoft spelling mistakes so we know they are not to be fixed. - kernel32/tests: Small spelling fix in a parameter name. - Assorted spelling fixes. - advapi32/tests: Actually test strings that expand to something bigger than their original size. - advapi32/tests: Add the trailing '\n' to an ok() call. - kernel32/tests: Test the expansion of indirect environment variable references. - winemenubuilder: Expand environment variable references in the shortcut's WorkDir, Description and IconPath fields. - Assorted spelling fixes. - -Gerald Pfeifer (3): - wininet: Fix type of a loop variable in HTTP_BuildHeaderRequestStr(). - kernel32: Fix type of a loop variable in SNOOP16_Entry(). - kernel32: Use setproctitle where applicable to set the process name. - -Gregor Münch (1): - msxml3: Fix typo. - -Hans Leidekker (9): - license: Update copyright info for the new year. - msvcrt: Fix _execv spec entries for the forwarding variants too. - msvcrt: _ftol returns a 64-bit value. - msvcr71: Add an implementation that forwards to msvcrt. - gdi32: Last parameter of GetICMProfile is an output parameter. - gdi32: Make GetICMProfile behave more like native. Rewrite ansi version as a wrapper and move color management functions to their own file. - gdi32: Add tests for GetICMProfile and SetICMMode. - mscms: Use NT directory for storing color profiles. - mscms: Open .icm files only when enumerating color profiles. - -Jacek Caban (9): - shdocvw: Added DWebBrowserEvents2 test. - shdocvw: Call OnFullScreen in put_FullScreen. - shdocvw: Call WindowSetResizable in put_Resizable. - shdocvw: Call StatusTextChange in set_status_text. - shdocvw: Store URL in BindStatusCallback. - shdocvw: Use more flexible mechanism instead of WB_WM_NAVIGATE2. - shdocvw: Delay creating URL moniker to bind_to_object call. - shdocvw: Do navigation in message handler. - shdocvw: Store headers as BSTR. - -James Hawkins (3): - msi: dest_path refers to the directory prefix, not the entire file path. - propsys: Add a stub implementation of propsys.dll. - msi: Add more MsiFormatRecord tests. - -Jason Green (1): - d3d9 tests: Correct some typos. - -Jonathan Ernst (1): - loader: Updated French man page. - -Juan Lang (4): - wintrust: Don't expect ImageGetCertificateData to succeed when Certificate is NULL. - crypt32: Don't release default crypto provider on process shutdown. - crypt32: Fix race condition in loading default provider. - hhctrl.ocx: Don't return uninitialized stream. - -Kai Blin (1): - gdi32: Fix spec file to export the right symbols for GetGlyphOutline. - -Ken Thomases (1): - winex11.drv: Accomodate XGetWindowProperty returning an actual format of something other than 32 for the TARGETS property. - -Lei Zhang (1): - ddraw: Register the DirectDraw 7 Object. - -Marcus Meissner (13): - server: Enumerate process in reverse. - mshtml: Check for This->frame. - wined3d: Check for overflows. - urlmon: Skip pstgmed related tests if NULL. - wmi: Initial version of wmi.dll. - gdi32: Fix possible NULL ptr in TRACE. - msi: Replaced msi_free() by LocalAlloc() since ConvertSidToStringSidW uses LocalAlloc(). - wined3d: Removed deadcode. - cmd: Include for time(). - wined3d: Initialize swapchain. - rpcrt4: Initialize CurrentHeader. - d3d9/tests: Initialize decl. - wininet: Check if buffer has overflowed potentially. - -Michael Stefaniuc (3): - winedump: Do not create a header file when not generating skeleton code. - winedump: Use the DEFINE_THISCALL_WRAPPER macro instead of the GET_THIS macro for functions with __thiscall calling convention. - winedump: Use a switch in the generated DllMain(). - -Pablo Spallanzani (1): - wined3d: Fix texture coordinate calculation in surface_blt_to_drawable. - -Paul Chitescu (1): - mscoree: Semi-stub for LoadStringRCEx and LoadStringRC. - -Paul Vriens (6): - kernel32/tests: FindFirstVolumeA is not available on win98. - advapi32/tests: Make tests run on win9x/NT4 again. - user32/tests: Run full test again on win95 and NT4. - msi/tests: Only use functions if they are implemented. - msi/tests: Only use functions if they are implemented. - kernel32/tests: Win9x returns a different last error. - -Reece H. Dunn (5): - user32: Make the clipboard tests pass on Vista. - user32: Make the class tests pass on Vista. - user32: Make the edit tests pass on Vista. - gdi32: Vista returns UNICODE_NOCHAR if a character does not exist. - advapi32: Fix some cred test failures on Vista and prevent it crashing. - -Rob Shearman (41): - include: Flesh out winhttp.h with more function declarations, typedefs and defines. - rpcrt4: Allocate a context handle if a NULL GUID is being unmarshalled. - rpcrt4: Add support for calculating the memory size of complex types with embedded non-conformant strings. - rpcrt4: Don't print fixmes for NDR types without a freeing function. - rpcrt4: Add traces to the start of TowerConstruct and TowerExplode. - winhttp: Add a stub for WinHttpOpen. - rpcrt4: Fix the calculation of element sizes for complex arrays by using a new function ComplexStructSize that doesn't touch the buffer to calculate the size. - rpcrt4: Handle complex arrays in calc_arg_size. - rpcrt4: The initialisation of [out] variables in the stubless code must be after the unmarshaling of [in] and [in, out] variables has been completed. - mlang: Implement Rfc1766ToLcidW. - rpcrt4: Allow NULL networkaddr and endpoint in rpcrt4_np_get_top_of_tower. - ole32: Partially implement ServerRpcChannelBuffer_GetDestCtx. - rpcrt4: Move the setting of retval_ptr outside of any particular stub phase in stub_do_args and stub_do_old_args. - rpcrt4: Add tests for RPC_FC_P_DEREF|RPC_FC_P_ONSTACK pointers. - comctl32: Keep on displaying the last frame of the animation after the animation has stopped. - comctl32: Support seeking to a particular frame. - rpcrt4: Add an exception handler for stubless object proxies. - rpcrt4: Only initialise the context handle to NULL in NdrContextHandleUnmarshall if it is an out-only or return one. - iphlpapi: Implement GetBestInterfaceEx. - kernel32: Initialise the top 16-bit stack frame to zero. - widl: Write out code for initialising out-only client context handles. - riched20: The wParam parameter to WM_GETTEXT contains the number of characters, not the number of bytes. - riched20: Always treat the nCount variable in the EM_GETTEXTEX handler as a character count. - rpcrt4: Implement asynchronous RPC support. - rpcrt4: Move the receiving of an individual fragment to a separate function. - rpcrt4: Remove some unimplemented win9x-only spec entries. - rpcrt4: Don't set BufferStart and BufferEnd in NdrStubCall2. - ole32: Don't get the HRESULT from the buffer if we get an RPC_S_CALL_FAILED status back from the runtime. - advapi32: Add more tests for SetEntriesInAcl. - ntdll: Fix the index check in RtlGetAce. - advapi32: Implement SetEntriesInAclW. - advapi32: Add a test for LookupAccountNameA on a well-known group. - advapi32: Implement LookupAccountNameW for well-known groups. - rpcrt4: Fix the error handling in RpcBindingSetAuthInfoA/W when RpcAuthInfo_Create fails. - rpcrt4: Pass the SPN input to RpcBindingSetAuthInfoA/W into InitializeSecurityContextW instead of AcquireCredentialsHandleA/W. - rpcrt4: Check the return value of RPCRT4_ClientAuthorize in RPCRT4_Send. - credui: The list should be the first parameter to the list_add_tail function. - credui: Return the state of the dialog's save checkbox to CredUIPromptForCredentials. - ntdsapi: Add tests for DsMakeSpnW. - ntdsapi: Implement DsMakeSpnW. - wininet: Pass the server name into InitializeSecurityContextW. - -Roderick Colenbrander (2): - wined3d: Fix glBlendColorEXT for use on RivaTNT. - wined3d: Don't use texture_rectangle for paletted textures. - -Roy Shea (1): - qmgr: Implement IClassFactory methods. - -Sin-ta Hsiea (2): - gdi32: Fix Traditional Chinese font mapping to "PMingLiU", "MingLiU". - winecfg: Add Traditional Chinese translation. - -Stefan Dösinger (15): - wined3d: Add a new IWineD3DResource::UnLoad method. - wined3d: Implement IWineD3DSurface::UnLoad. - wined3d: Implement IWineD3DVertexBuffer::UnLoad. - wined3d: Implement IWineD3DIndexBuffer::UnLoad. - wined3d: Implement IWineD3DVolume::UnLoad. - wined3d: Implement IWineD3DTexture::UnLoad. - wined3d: Implement IWineD3DCubeTexture::UnLoad. - wined3d: Implement VolumeTexture::UnLoad. - d3d9: Reject IDirect3DDevice9::Reset with active default pool resources. - wined3d: Unload all resources on Reset. - wined3d: Keep track of shaders. - wined3d: Reset the shader state on shader_*_destroy. - wined3d: Destroy arb shaders on shader destroy. - wined3d: Destroy opengl shaders on reset. - wined3d: Clear the constant list before finding constants. - -Stefan Leichter (1): - advapi32: Added some tests for QueryServiceConfig2A/W. - -Tony Wasserka (1): - d3dx9: Start implementation of d3dx9_36. - --- -Alexandre Julliard -julliard@winehq.org +This is release 0.9.55 of Wine, a free implementation of Windows on Unix. + +What's new in this release: + - Direct3D improvements, including driver version emulation. + - Beginnings of support for OLE objects in Richedit. + - Several fixes to the animation control. + - A bunch of fixes for regression test failures. + - Lots of bug fixes. + +Because of lags created by using mirrors, this message may reach you +before the release is available at the public sites. The sources will +be available from the following locations: + + http://ibiblio.org/pub/linux/system/emulators/wine/wine-0.9.55.tar.bz2 + http://prdownloads.sourceforge.net/wine/wine-0.9.55.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 or CVS +repositories. Check respectively http://www.winehq.org/site/git or +http://www.winehq.org/site/cvs for details. + +If you fix something, please submit a patch; instructions on how to do +this can be found at http://www.winehq.org/site/sending_patches + +Wine is available thanks to the work of many people. See the file +AUTHORS in the distribution for the complete list. + +---------------------------------------------------------------- + +Changes since 0.9.54: + +Alexander Nicolaysen Sørnes (1): + shell32: Use LocalFree in CommandLineToArgvW. + +Alexandre Julliard (18): + winex11: Abstract the depth->bpp conversion and use it in X11DRV_DIB_CreateDIBFromPixmap. + winex11: Remove unneeded check on bitmap depth, screen bpp cannot be 15. + shell32: Fix permissions of newly-created directories. + gdi32: Avoid locking in CreateCompatibleBitmap. + gdi32: Get rid of a few more uses of DC_GetDCPtr. + gdi32: Don't hold the GDI lock when calling DC_InitDC. + gdi32: Avoid locking in BITMAP_CopyBitmap. + gdi32: Use a separate critical section for freetype locking instead of relying on the GDI lock. + gdi32: Get rid of DC_GetDCPtr in font functions. + gdi32: Get rid of DC_GetDCPtr in the GDI object functions. + winex11: Add a critical section for the palette global variables instead of relying on the GDI lock. + gdi32: Get rid of DC_GetDCPtr in the palette functions. + gdi32: DC_GetDCPtr and DC_ReleaseDCPtr are not longer used. + winex11: Don't erase the desktop window synchronously on resizes to prevent deadlocks. + winex11: Use the gdi display when initializing the keyboard to avoid creating a second display connection. + winex11: Only update the virtual screen rect once in xinerama_init to minimize race conditions. + tests: Add a helper routine to wait for a child process and propagate its result correctly. + localspl: Avoid sizeof in a trace. + +Alistair Leslie-Hughes (7): + msxml3: Validated attribute name. + msxml3: Corrected Entity Reference Test. + msxml3: Correct createElement return value for an invalid type. + kernel32: Add RegisterApplicationRestart stub. + gdiplus: Add GdipSetPenMode stub. + gdiplus: Add GdipSetStringFormatFlags stub. + msxml3: Corrected test text. + +Andre Wisplinghoff (1): + winecfg: Enable add button when choosing lib from combobox (Libraries tabsheet). + +Andrew Riedi (2): + user32: Test destroying the cursor of a parent process. + user32: winex11.drv has support for color cursors now. + +Andrew Talbot (10): + winemp3.acm: Remove unneeded casts. + wineps.drv: Remove unneeded casts. + winex11.drv: Remove unneeded casts. + winex11.drv: Remove unneeded casts. + wininet: Remove unneeded casts. + winmm: Remove unneeded casts. + wintab32: Remove unneeded cast. + msvfw32: Avoid possible dereference of NULL pointer (Coverity). + wnaspi32: Remove unneeded cast. + ws2_32: Remove unneeded casts. + +Andrey Esin (1): + cmd: Additions to Russian translation. + +Aric Stewart (1): + gdi32: Child fonts need to be scaled like their parent. With input from Dmitry Timoshkov. + +Bang Jun-young (4): + crypt32: Include wine/port.h for snprintf(). + user32: Fix EndMenu() to match the PSDK. + riched20: Include wine/port.h for vsnprintf(). + comctl32: Fix invalid syntax. + +Christopher Harvey (1): + winex11: Added WGL_BIND_TO_TEXTURE_DEPTH_NV to ConvertAttribWGLtoGLX. + +Colin Finck (2): + widl: Support Windows paths in dup_basename and make_token. + widl: Write the TLB file in binary mode, so the line endings won't be changed. + +Detlef Riekenberg (7): + localspl: Initialize pointers in struct PRINTPROVIDOR. + localspl: Implement fpGetPrinterDriverDirectory. + winspool: Use the backend for GetPrinterDriverDirectory. + gdi32: Add stub for GdiInitSpool and GdiGetSpoolMessage. + url: Add a stub for AddMIMEFileTypesPS. + localspl: Implement fpAddPrinterDriverEx. + winspool: Use the backend for AddPrinterDriverEx. + +Dmitry Timoshkov (2): + kernel32: LOADPARAMS16->showCmd can be NULL, do not crash in that case. + kernel32: Separate modifier from charset before detecting the charset codepage. + +Eric Pouech (27): + dbghelp: Return the size of each directory instead of passing a pointer to it. + dbghelp: Fixed the suspend count when creating a minidump in the middle of an exception. + dbghelp: Removed double assignment of checksum. + dbghelp: Store the PE version information in module block. + winedbg: Implemented the pXX request in gdb proxy. + riched20: Start handling OLE objects inside richedit. + riched20: Handle the zoom in OLE objects. + riched20: Correctly handle the wrapping when graphics are used. + riched20: Invert graphics when they are under the selection. + riched20: Support a couple of paragraphs attributes out of RTF stream reading. + riched20: Added support for image reading from RTF stream. + riched20: Start implementing object reading out RTF stream. + riched20: Make use of the size info in REOBJECT if present. + dbghelp: Fixed the types we want to load at first. + dbghelp: Added missing basic types for booleans and integers. + dbghelp: Pass the 'details' flags to _fetch_type so that we can simplify some code around. + dbghelp: Fix mixed up return and this type in MFunction V2. + dbghelp: Added HRESULT as new basic type (and some doc about basic types ids). + dbghelp: Added support for some V3 fields in structure parsing. + dbghelp: Added support for register v3 in msc. + dbghelp: Added preliminary support for a strange stack variable object. + dbghelp: Added support for labels outside functions (and used it in msc parsing). + dbghelp: Added basic support for base class information. + dbghelp: Extended the internal enumeration information so that we know the underlying integral type. + dbghelp: Attempt to cache some basic symbol types for easier and faster code. + dbghelp: When sending back information about a global symbol, only demangle the class & field/method name. + dbghelp: Disable the S_PUB_FUNC_XXX msc symbols until we know what they do (the first guess is wrong anyway). + +Francois Gouget (23): + shell32/tests: Fix a couple of copy/paste errors. + shell32: Add some SLDF_XXX values, EXP_PROPERTYSTORAGE, and EXP_PROPERTYSTORAGE_SIG. + user32: Fix a typo in the StretchDIBits stub name. + winedump: Use the standard SLDF_XXX flag names instead of inventing new ones. Add the missing flags. + winedump: Track unknown lnk flags and dump them. + winedump: Dump the raw data when finding an unknown block in an lnk file. + winedump: Switch the block dumping code to be block-oriented, rather then flag oriented, so it is resilient to order changes. + winedump: Add support for dumping SZ_LINK and SPECIAL_FOLDER data blocks. + ddraw/tests: Fix compilation on systems that don't support nameless unions. + mapi32: Add an API documentation stub to make winapi_check happy. + ntdsapi: Add an API documentation stub to make winapi_check happy. + winex11.drv: Add some API documentation stubs to make winapi_check happy. + msvcrt: __CxxDetectRethrow() and __CxxQueryExceptionSize() are implemented now so export them. + winapi_check: Update win32.api for acledit.dll, ctapi32.dll and inetcomm.dll. + winapi_check: Assorted win32.api updates. + winapi_check: Update win32.api for d3dx8.dll. + d3dx8core.h: Remove some extraneous #include directives. + d3dx8: Fix the D3DXMatrixAffineTransformation() prototype. + d3dx8: Make d3dx8core.h C++ compatible. + d3dx8: Add the d3dx8mesh.h header and move the relevant function declarations there. + d3dx8: Fix the D3DXAssembleShaderFromFileA/W() prototypes. + comctl32/tests: Call InitCommonControlsEx() if available, fall back to InitCommonControls() for the older controls, and skip the tests altogether for the newer ones. + riched20: Fix the name of the lpUsedDefChar field of GETTEXTEX. + +Gerald Pfeifer (2): + d3d9: Fix the type of three loop variables. + configure: Use GCC's -Wtype-limits if possible. + +Hans Leidekker (3): + wininet: Make sure not to overwrite any caller supplied authorization header. + wininet: Send HTTP/1.1 requests by default. + wininet: Add zero value content length header to POST requests only. + +Jacek Caban (28): + urlmon: Added HlinkParseDisplayNameEx implementation. + urlmon: Added MkParseDisplayNameEx tests. + hlink: Call AddRef of correct interface in ExtServUnk_QueryInterface. + hlink.idl: Added more function declarations. + hlink: Added HlinkParseDisplayName implementation. + hlink: Added HlinkParseDisplayName tests. + hlink: Added HlinkResolveMonikerForData implementation. + hlink: Added HlinkResolveMonikerForData tests. + hlink: Added standard comments. + hlink: Don't prefer native version. + urlmon: Added comments about missing MIME filters. + widl: Ignore ATTR_LOCAL in create_msft_typeinfo. + urlmon: Added CopyStgMedium implementation. + urlmon: Fixed tests. + urlmon: Return better error results. + mshtml: Added more about protocol tests. + urlmon: Separate buffer from stream object. + urlmon: Abstract ProtocolStream object. + urlmon: Don't create stgmed_obj for binding to object. + urlmon: Added BINDSTATUS_CACHEFILENAMEAVAILABLE support. + urlmon: Added support for binding to IID_IUnknown storage (cache file). + urlmon: Correctly handle BINDF_NEEDFILE flag in http protocol. + urlmon: Added more protocol tests. + itss: Added BINDF_NEEDFILE test. + urlmon: Added more tests. + mshtml: Update wine_url in nsIURI::SetPath. + urlmon: Added gecko_installer_workaround to url.c tests. + urlmon: Fixed ref count leak. + +James Hawkins (16): + kernel32: Factor out the VerifyVersionInfo tests into their own function. + version: Return ERROR_RESOURCE_DATA_NOT_FOUND if the file does not have version information. + msi: Add tests for using single quotes in an INSERT query. + msi: Implement the MSIMODIFY_ASSIGN action of MsiViewModify for the streams table. + msi: Add tests for MsiGetFileVersion. + msi: Only convert output strings if the call succeeded. + msi: Translate ERROR_BAD_PATHNAME into ERROR_FILE_NOT_FOUND. + msi: Return ERROR_INVALID_PARAMETER if a string pointer is non-NULL and the size pointer is NULL. + msi: Return ERROR_FILE_INVALID if the file has no version information. + msi: Leave room for the NULL terminator. + msi: Return the string length even if the string is NULL. + msi: Return ERROR_MORE_DATA if the size is too small. + msi: Add more tests for MsiFormatRecord. + msi: Reimplement MsiFormatRecord. + msi: Fix handling of the NULL separator when writing registry values. + msi: Test using carriage returns in SQL queries and imported tables. + +Jens Nestler (1): + kernel32: Don't fail unconditionally in MoveFile for directories with flag MOVEFILE_REPLACE_EXISTING. + +Johan Gardell (1): + user32: Added support for SPI_SETMOUSESPEED in SystemParametersInfoW. + +Juan Lang (1): + rsaenh: Merge the encrypting and decrypting states, as encrypting and decrypting are allowed with the same key. + +Kirill K. Smirnov (2): + systray: Properly track errors. + systray: Add support for NIS_HIDDEN flag. + +Lars-Ake Fredlund (1): + winex11: Don't create a mapping if X11DRV_PALETTE_VIRTUAL is set. + +Lei Zhang (3): + comctl32: Use wine_dbgstr_rect() in traces. + user32: Use wine_dbgstr_rect() in traces. + quartz: Add VideoRendererDefault. + +Marcus Meissner (3): + wordpad: Remove condition that never triggers. + atl: Check for NULL. + pdh: Fixed wrong condition. + +Michael Stefaniuc (3): + user32: Remove duplicated get_hook_proc() function. + olecli: Remove duplicated typedefs/enums. + msi: Fix "type of 'x' defaults to 'int'" warnings. + +Paul Chitescu (1): + ntoskrnl.exe: Implement MmPageEntireDriver and MmResetDriverPaging. + +Paul Vriens (4): + include/wintrust.h: Add missing members to CRYPT_PROVIDER_DATA struct (fixes some wintrust tests on Windows). + wintrust/tests: Use GetModuleHandleA instead of LoadLibraryA. + rpcrt4/tests: Change test for Windows 2003. + rpcrt4/tests: Skip rest of the tests if we fail. + +Reece H. Dunn (9): + comctl32: Proper fix redrawing the trackbar background with themes enabled. + gdiplus: Fix the bezier arc path test on all Windows platforms. + msxml3: Fix the domdoc test failures. + cabinet: Make the fdi tests pass on Vista. + ddraw: Spelling fixes in the d3d test output. + gdi32: Improve the failure reporting in the bitmap tests. + uxtheme: Fix the system tests so they pass on Vista. + comctl32: Vista sends an unidentified message when destroying datetime and monthcal windows. + user32: Make the listbox tests pass in directories other than dlls/user32/tests. + +Rob Shearman (30): + secur32: Move the detection of NULL credentials from AcquireCredentialsHandle to InitializeSecurityContext. + secur32: If using cached credentials failed in InitializeSecurityContext then fail with SEC_E_NO_CREDENTIALS instead of carrying on with a blank password. + secur32: Try to retrive credentials by using the credential manager to retrieve credentials saved for the target server in InitializeContextHandleW, if possible. + secur32: Initialise more pointers in helper to NULL. + oleaut32: Fix big memory leak in xCall. + widl: Don't search for a import file name with a path in the include directories for compatibility with MIDL. + widl: Output code for initialising and freeing full pointer translation tables. + mapi32: Add a stub implementation of HrQueryAllRows@24. + ole32: Add a stub implementation of CreatePointerMoniker. + oleaut32: Fix a leak of a typelib object in OLEFontImpl_GetTypeInfo. + oleaut32: Fix a memory leak in the olefont tests. + rpcrt4: Fix some incorrect checks in RPCRT4_Receive. + oleaut32: Fix some reference count leaks in the tmarshal test. + oleaut32: Fix a leak of bmi in OLEPictureImpl_LoadGif. + comctl32: In certain circumstances, native comctl32's animation control accepts negative start positions for the ACM_PLAY message. + advapi32: Fix the size calculation in StartServiceW. + wine.inf: Make UI effects default to on. + oleaut32: Fix some memory leaks in the safearray tests. + ole32: Add tests for CreatePointerMoniker. + ole32: Add pointer moniker implementation. + wininet: HTTP_Connect should fail if a NULL or empty hostname is passed in. + rpcrt4: Fix memory leaks in the rpc tests. + comctl32: Get the background colour in ANIMATE_PaintFrame, instead of just in WM_PAINT. + ntdll: The FileMailslotSetInformation and FileCompletionInformation cases of NtSetInformationFile don't need the fd. + server: Always try return a named pipe server that is listening from find_available_server. + ws2_32: Add a FIXME for WS_SIO_GET_EXTENSION_FUNCTION_POINTER in WSAIoctl. + rpcrt4: Fix potential memory leaks in RPCRT4_Receive. + rpcrt4: Fix potential memory leaks on error paths in RPCRT4_io_thread. + comctl32: Don't get the background colour in ANIMATE_PaintFrame as this can be called inside a critical section. + comctl32: Move the getting of the DC outside of ANIMATE_DrawFrame. + +Roderick Colenbrander (5): + wined3d: Make sure to set the color key when it is needed including for index_in_alpha. + wined3d: Reload the palette on a color key change. This fixes the ddex4/ddex5 samples from the dx7 sdk. + wined3d: Allow read back of P8 surfaces. This fixes some of the redrawing issues in Red Alert. + wined3d: Redownload the surface data in case of a palette change. This fixes a lot of redrawing problems in Red Alert. + wined3d: Upload p8 palette using GL_ALPHA instead of GL_RED. + +Stefan Dösinger (30): + wined3d: Beware of texture_rectangle NP2 support in Reset. + wined3d: Update the auto depth stencil buffer size on reset. + wined3d: Unload implicit depth stencil buffers correctly. + wined3d: Destroy FBOs and reset pointers on Reset. + wined3d: Move some UnLoad code to the base texture class. + wined3d: Mark textures dirty on UnLoad. + wined3d: De-Statify depth blit opengl resources. + d3d9: Some drivers allow non-aligned offsets. + wined3d: Make Clear aware of the depth stencil sharing. + wined3d: Update the gl rectangle when adjusting surface sizes. + wined3d: D3DTADDRESS_WRAP on conditional NP2 textures clamps to edge. + wined3d: Some texture transform test corrections. + d3d9/tests: Be less picky about X8L8V8U8 precision. + d3d9/tests: Accept the rejection of non-standard fixed function attrib types. + wined3d: Correct the srgb reading check. + wined3d: Fix dxtn format check. + wined3d: Move the float format check to the big switch statement. + wined3d: Move vertex buffer vbo creation to PreLoad. + wined3d: Recreate the contexts on _Reset. + wined3d: Restore the stateblock after Reset. + wined3d: Tear down the dummy textures before resetting. + wined3d: Move the highpart of the driver version to the gl structure. + wined3d: Separate OpenGL and driver version. + wined3d: Create VBOs. + ddraw: Some drivers return a refresh rate of 0. + wined3d: Add infrastructure for faking driver versions. + wined3d: Add some ATI cards to the version database. + wined3d: Reject unsupported modes when restting the device. + d3d9: Implement the device lost state. + wined3d: Restore the Window size on reset. + +Stefan Leichter (1): + advapi32: Fix the failing QueryServiceConfig2 test on platforms win2k3 and vista. + +-- +Alexandre Julliard +julliard@winehq.org diff --git a/ChangeLog b/ChangeLog index 71832880d9e..b1cfd817b39 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,1086 @@ +2008-02-08 Alistair Leslie-Hughes + + * dlls/msxml3/tests/xmldoc.c: + msxml3: Corrected test text. + +2008-02-08 Dmitry Timoshkov + + * dlls/kernel32/locale.c: + kernel32: Separate modifier from charset before detecting the charset codepage. + +2008-02-08 Reece H. Dunn + + * dlls/user32/tests/listbox.c: + user32: Make the listbox tests pass in directories other than dlls/user32/tests. + +2008-02-08 Detlef Riekenberg + + * dlls/winspool.drv/info.c: + winspool: Use the backend for AddPrinterDriverEx. + + * dlls/localspl/localspl_main.c: + localspl: Implement fpAddPrinterDriverEx. + +2008-02-08 Paul Vriens + + * dlls/rpcrt4/tests/rpc.c: + rpcrt4/tests: Skip rest of the tests if we fail. + + * dlls/rpcrt4/tests/rpc.c: + rpcrt4/tests: Change test for Windows 2003. + +2008-02-08 Roderick Colenbrander + + * dlls/wined3d/surface.c: + wined3d: Upload p8 palette using GL_ALPHA instead of GL_RED. + +2008-02-02 Lei Zhang + + * dlls/quartz/main.c, dlls/quartz/quartz_private.h, dlls/quartz/regsvr.c, + dlls/quartz/videorenderer.c, include/uuids.h: + quartz: Add VideoRendererDefault. + +2008-02-07 Andrew Talbot + + * dlls/ws2_32/async.c, dlls/ws2_32/socket.c: + ws2_32: Remove unneeded casts. + + * dlls/wnaspi32/winaspi16.c: + wnaspi32: Remove unneeded cast. + +2008-02-07 Juan Lang + + * dlls/rsaenh/rsaenh.c: + rsaenh: Merge the encrypting and decrypting states, as encrypting and decrypting + are allowed with the same key. + +2008-02-07 Johan Gardell + + * dlls/user32/sysparams.c: + user32: Added support for SPI_SETMOUSESPEED in SystemParametersInfoW. + +2008-02-07 Colin Finck + + * tools/widl/write_msft.c: + widl: Write the TLB file in binary mode, so the line endings won't be changed. + + * tools/widl/utils.c, tools/widl/widl.c: + widl: Support Windows paths in dup_basename and make_token. + +2008-02-07 Alexandre Julliard + + * dlls/localspl/localspl_main.c: + localspl: Avoid sizeof in a trace. + +2008-02-07 Rob Shearman + + * dlls/comctl32/animate.c: + comctl32: Move the getting of the DC outside of ANIMATE_DrawFrame. + This allows the handle to the DC to be passed in the WM_CTLCOLORSTATIC + message sent to the parent. + +2008-02-06 Stefan Dösinger + + * dlls/wined3d/device.c: + wined3d: Restore the Window size on reset. + + * dlls/d3d9/d3d9_private.h, dlls/d3d9/device.c, dlls/d3d9/tests/device.c: + d3d9: Implement the device lost state. + + * dlls/d3d9/tests/device.c, dlls/wined3d/device.c: + wined3d: Reject unsupported modes when restting the device. + + * dlls/wined3d/directx.c: + wined3d: Add some ATI cards to the version database. + + * dlls/wined3d/directx.c: + wined3d: Add infrastructure for faking driver versions. + Often the Linux / MacOS graphics driver version is of no use for + finding a proper driver version to report to the D3D app. So this + patch adds some infrastructure for easy hardcoding of card specific + driver versions to report to the application. This helps applications + which make assumptions based on the driver version, like bug + workarounds. + +2008-01-26 Reece H. Dunn + + * dlls/comctl32/tests/datetime.c, dlls/comctl32/tests/monthcal.c: + comctl32: Vista sends an unidentified message when destroying datetime and + monthcal windows. + +2008-02-07 Reece H. Dunn + + * dlls/uxtheme/tests/system.c: + uxtheme: Fix the system tests so they pass on Vista. + +2008-02-07 Alexandre Julliard + + * dlls/advapi32/tests/security.c, dlls/kernel32/tests/actctx.c, + dlls/kernel32/tests/toolhelp.c, dlls/ntdll/tests/exception.c, + dlls/ole32/tests/marshal.c, dlls/rpcrt4/tests/server.c, + dlls/shell32/tests/shellpath.c, dlls/user32/tests/cursoricon.c, + include/wine/test.h: + tests: Add a helper routine to wait for a child process and propagate its + result correctly. + +2008-02-06 James Hawkins + + * dlls/msi/database.c, dlls/msi/tests/db.c: + msi: Test using carriage returns in SQL queries and imported tables. + +2008-02-05 Andrey Esin + + * programs/cmd/Ru.rc: + cmd: Additions to Russian translation. + +2008-02-05 Detlef Riekenberg + + * dlls/url/url.spec, dlls/url/url_main.c: + url: Add a stub for AddMIMEFileTypesPS. + +2008-02-05 Christopher Harvey + + * dlls/winex11.drv/opengl.c: + winex11: Added WGL_BIND_TO_TEXTURE_DEPTH_NV to ConvertAttribWGLtoGLX. + +2008-02-03 Bang Jun-young + + * dlls/comctl32/listview.c: + comctl32: Fix invalid syntax. + +2008-01-29 Alexander Nicolaysen Sørnes + + * dlls/shell32/shell32_main.c: + shell32: Use LocalFree in CommandLineToArgvW. + +2008-02-02 Andrew Talbot + + * dlls/msvfw32/drawdib.c: + msvfw32: Avoid possible dereference of NULL pointer (Coverity). + +2008-02-01 Detlef Riekenberg + + * dlls/gdi32/gdi32.spec, dlls/gdi32/printdrv.c: + gdi32: Add stub for GdiInitSpool and GdiGetSpoolMessage. + +2008-01-30 Lars-Ake Fredlund + + * dlls/winex11.drv/palette.c: + winex11: Don't create a mapping if X11DRV_PALETTE_VIRTUAL is set. + +2008-01-24 Lei Zhang + + * dlls/user32/combo.c, dlls/user32/defwnd.c, dlls/user32/listbox.c, + dlls/user32/nonclient.c, dlls/user32/painting.c, dlls/user32/spy.c, + dlls/user32/uitools.c, dlls/user32/winpos.c: + user32: Use wine_dbgstr_rect() in traces. + + * dlls/comctl32/comboex.c, dlls/comctl32/monthcal.c, + dlls/comctl32/pager.c, dlls/comctl32/propsheet.c, + dlls/comctl32/rebar.c, dlls/comctl32/status.c, dlls/comctl32/tab.c, + dlls/comctl32/toolbar.c, dlls/comctl32/trackbar.c, + dlls/comctl32/treeview.c: + comctl32: Use wine_dbgstr_rect() in traces. + +2008-02-06 Eric Pouech + + * dlls/dbghelp/msc.c: + dbghelp: Disable the S_PUB_FUNC_XXX msc symbols until we know what they do + (the first guess is wrong anyway). + + * dlls/dbghelp/symbol.c: + dbghelp: When sending back information about a global symbol, only demangle + the class & field/method name. + + * dlls/dbghelp/dwarf.c: + dbghelp: Attempt to cache some basic symbol types for easier and faster code. + + * dlls/dbghelp/dbghelp_private.h, dlls/dbghelp/dwarf.c, + dlls/dbghelp/msc.c, dlls/dbghelp/stabs.c, dlls/dbghelp/type.c: + dbghelp: Extended the internal enumeration information so that we know the + underlying integral type. + + * dlls/dbghelp/type.c: + dbghelp: Added basic support for base class information. + As we don't support C++ for now, we just return FALSE for all cases. + + * dlls/dbghelp/dbghelp_private.h, dlls/dbghelp/dwarf.c, + dlls/dbghelp/msc.c, dlls/dbghelp/symbol.c, dlls/dbghelp/type.c: + dbghelp: Added support for labels outside functions (and used it in msc parsing). + + * dlls/dbghelp/msc.c, include/wine/mscvpdb.h, tools/winedump/msc.c: + dbghelp: Added preliminary support for a strange stack variable object. + + * dlls/dbghelp/msc.c: + dbghelp: Added support for register v3 in msc. + + * dlls/dbghelp/msc.c: + dbghelp: Added support for some V3 fields in structure parsing. + + * dlls/dbghelp/msc.c, include/wine/mscvpdb.h: + dbghelp: Added HRESULT as new basic type (and some doc about basic types ids). + + * include/wine/mscvpdb.h: + dbghelp: Fix mixed up return and this type in MFunction V2. + + * dlls/dbghelp/msc.c: + dbghelp: Pass the 'details' flags to _fetch_type so that we can simplify some + code around. + + * dlls/dbghelp/msc.c: + dbghelp: Added missing basic types for booleans and integers. + +2008-02-07 Andrew Riedi + + * dlls/user32/cursoricon.c: + user32: winex11.drv has support for color cursors now. + +2008-02-06 Andrew Talbot + + * dlls/wintab32/wintab32.c: + wintab32: Remove unneeded cast. + +2008-02-06 Rob Shearman + + * dlls/comctl32/animate.c: + comctl32: Don't get the background colour in ANIMATE_PaintFrame as this can + be called inside a critical section. + This could therefore create a deadlock if the processing for + WM_CTLCOLORSTATIC ends up sending certain messages to the animate control. + So move the retrieval of the background colour into the callers of + ANIMATE_PaintFrame but outside of any critical section. + +2008-02-06 Jacek Caban + + * dlls/urlmon/binding.c: + urlmon: Fixed ref count leak. + + * dlls/urlmon/tests/Makefile.in, dlls/urlmon/tests/url.c: + urlmon: Added gecko_installer_workaround to url.c tests. + +2008-02-06 Alexandre Julliard + + * dlls/winex11.drv/xinerama.c: + winex11: Only update the virtual screen rect once in xinerama_init to minimize + race conditions. + + * dlls/winex11.drv/keyboard.c, dlls/winex11.drv/x11drv.h, + dlls/winex11.drv/x11drv_main.c: + winex11: Use the gdi display when initializing the keyboard to avoid creating + a second display connection. + + * dlls/winex11.drv/winpos.c: + winex11: Don't erase the desktop window synchronously on resizes to prevent + deadlocks. + +2008-02-06 Paul Vriens + + * dlls/wintrust/tests/crypt.c: + wintrust/tests: Use GetModuleHandleA instead of LoadLibraryA. + +2008-01-26 Reece H. Dunn + + * dlls/gdi32/tests/bitmap.c: + gdi32: Improve the failure reporting in the bitmap tests. + +2008-01-27 Reece H. Dunn + + * dlls/ddraw/tests/d3d.c: + ddraw: Spelling fixes in the d3d test output. + +2008-01-26 Reece H. Dunn + + * dlls/cabinet/tests/fdi.c: + cabinet: Make the fdi tests pass on Vista. + +2008-01-29 Jens Nestler + + * dlls/kernel32/path.c: + kernel32: Don't fail unconditionally in MoveFile for directories with flag + MOVEFILE_REPLACE_EXISTING. + +2008-02-05 Kirill K. Smirnov + + * programs/explorer/systray.c: + systray: Add support for NIS_HIDDEN flag. + + * dlls/shell32/systray.c, dlls/shell32/tests/systray.c, + programs/explorer/systray.c: + systray: Properly track errors. + +2008-01-24 Andrew Riedi + + * dlls/user32/tests/cursoricon.c: + user32: Test destroying the cursor of a parent process. + +2008-02-05 Paul Chitescu + + * dlls/ntoskrnl.exe/ntoskrnl.c, dlls/ntoskrnl.exe/ntoskrnl.exe.spec: + ntoskrnl.exe: Implement MmPageEntireDriver and MmResetDriverPaging. + +2008-02-06 Francois Gouget + + * dlls/riched20/editor.c, dlls/riched20/tests/editor.c, + include/richedit.h: + riched20: Fix the name of the lpUsedDefChar field of GETTEXTEX. + +2008-01-27 Stefan Dösinger + + * dlls/ddraw/tests/ddrawmodes.c: + ddraw: Some drivers return a refresh rate of 0. + +2008-02-05 Stefan Dösinger + + * dlls/wined3d/vertexbuffer.c: + wined3d: Create VBOs. + + * dlls/wined3d/directx.c, include/wine/wined3d_gl.h: + wined3d: Separate OpenGL and driver version. + + * dlls/wined3d/directx.c: + wined3d: Move the highpart of the driver version to the gl structure. + While 6.14 is a sane default, we might want to override it on a + per-driver basis, if we have really old Windows drivers on some cards. + + * dlls/wined3d/device.c: + wined3d: Tear down the dummy textures before resetting. + In theory the opengl library should release the gl resources when we + destroy the context, and the stateblock reset will recreate the dummy + textures, but I think it is cleaner to do this explicitly. + + * dlls/wined3d/device.c: + wined3d: Restore the stateblock after Reset. + +2008-02-05 Andrew Talbot + + * dlls/winmm/message16.c, dlls/winmm/winmm.c: + winmm: Remove unneeded casts. + +2008-02-05 Roderick Colenbrander + + * dlls/wined3d/surface_base.c: + wined3d: Redownload the surface data in case of a palette change. This fixes + a lot of redrawing problems in Red Alert. + + * dlls/wined3d/surface.c: + wined3d: Allow read back of P8 surfaces. This fixes some of the redrawing + issues in Red Alert. + +2008-01-29 Roderick Colenbrander + + * dlls/wined3d/surface.c: + wined3d: Reload the palette on a color key change. This fixes the ddex4/ddex5 + samples from the dx7 sdk. + + * dlls/wined3d/surface.c: + wined3d: Make sure to set the color key when it is needed including for + index_in_alpha. + +2008-02-05 Michael Stefaniuc + + * dlls/msi/format.c: + msi: Fix "type of 'x' defaults to 'int'" warnings. + +2008-02-04 Detlef Riekenberg + + * dlls/winspool.drv/info.c, dlls/winspool.drv/wspool.c, + dlls/winspool.drv/wspool.h: + winspool: Use the backend for GetPrinterDriverDirectory. + + * dlls/localspl/localspl_main.c: + localspl: Implement fpGetPrinterDriverDirectory. + + * dlls/localspl/localspl_main.c: + localspl: Initialize pointers in struct PRINTPROVIDOR. + +2008-02-05 Alexandre Julliard + + * dlls/gdi32/dc.c, dlls/gdi32/gdi_private.h: + gdi32: DC_GetDCPtr and DC_ReleaseDCPtr are not longer used. + + * dlls/gdi32/palette.c: + gdi32: Get rid of DC_GetDCPtr in the palette functions. + + * dlls/winex11.drv/palette.c: + winex11: Add a critical section for the palette global variables instead of + relying on the GDI lock. + + * dlls/gdi32/brush.c, dlls/gdi32/gdiobj.c, dlls/gdi32/pen.c: + gdi32: Get rid of DC_GetDCPtr in the GDI object functions. + + * dlls/gdi32/font.c: + gdi32: Get rid of DC_GetDCPtr in font functions. + + * dlls/gdi32/freetype.c: + gdi32: Use a separate critical section for freetype locking instead of relying + on the GDI lock. + + * dlls/gdi32/bitmap.c: + gdi32: Avoid locking in BITMAP_CopyBitmap. + + * dlls/gdi32/bitmap.c: + gdi32: Don't hold the GDI lock when calling DC_InitDC. + + * dlls/gdi32/brush.c, dlls/gdi32/dib.c, dlls/gdi32/font.c: + gdi32: Get rid of a few more uses of DC_GetDCPtr. + + * dlls/gdi32/bitmap.c: + gdi32: Avoid locking in CreateCompatibleBitmap. + +2008-02-05 Francois Gouget + + * dlls/comctl32/tests/comboex.c, dlls/comctl32/tests/datetime.c, + dlls/comctl32/tests/header.c, dlls/comctl32/tests/listview.c, + dlls/comctl32/tests/monthcal.c, dlls/comctl32/tests/progress.c, + dlls/comctl32/tests/rebar.c, dlls/comctl32/tests/treeview.c: + comctl32/tests: Call InitCommonControlsEx() if available, fall back to + InitCommonControls() for the older controls, and skip the tests altogether + for the newer ones. + +2008-02-04 Reece H. Dunn + + * dlls/msxml3/tests/domdoc.c: + msxml3: Fix the domdoc test failures. + +2008-02-05 Stefan Dösinger + + * dlls/wined3d/device.c: + wined3d: Recreate the contexts on _Reset. + +2008-01-08 Stefan Dösinger + + * dlls/wined3d/device.c, dlls/wined3d/vertexbuffer.c, + dlls/wined3d/wined3d_private.h: + wined3d: Move vertex buffer vbo creation to PreLoad. + +2008-02-04 Stefan Dösinger + + * dlls/wined3d/directx.c: + wined3d: Move the float format check to the big switch statement. + + * dlls/wined3d/directx.c: + wined3d: Fix dxtn format check. + We can't return WINED3D_OK straight away because we have yet to check + the other flags, like sRGB correction. + + * dlls/wined3d/directx.c: + wined3d: Correct the srgb reading check. + + * dlls/d3d9/tests/visual.c: + d3d9/tests: Accept the rejection of non-standard fixed function attrib types. + +2008-02-01 Stefan Dösinger + + * dlls/d3d9/tests/visual.c: + d3d9/tests: Be less picky about X8L8V8U8 precision. + + * dlls/d3d9/tests/visual.c: + wined3d: Some texture transform test corrections. + + * dlls/d3d9/tests/visual.c, dlls/wined3d/basetexture.c: + wined3d: D3DTADDRESS_WRAP on conditional NP2 textures clamps to edge. + Conditional NP2 textures in Direct3D do not support D3DTADDRESS_WRAP + texture addressing. Similarly, GL_ARB_texture_rectangle textures do + not support GL_REPEAT. This patch adds a test which shows that _WRAP + clamps to the texture edge and implements that. + +2008-01-27 Stefan Dösinger + + * dlls/wined3d/device.c: + wined3d: Update the gl rectangle when adjusting surface sizes. + + * dlls/wined3d/device.c, dlls/wined3d/drawprim.c, + dlls/wined3d/wined3d_private.h: + wined3d: Make Clear aware of the depth stencil sharing. + + * dlls/d3d9/tests/device.c: + d3d9: Some drivers allow non-aligned offsets. + + * dlls/wined3d/arb_program_shader.c, dlls/wined3d/baseshader.c, + dlls/wined3d/device.c, dlls/wined3d/drawprim.c, + dlls/wined3d/glsl_shader.c, dlls/wined3d/wined3d_private.h: + wined3d: De-Statify depth blit opengl resources. + +2008-01-25 Stefan Dösinger + + * dlls/wined3d/basetexture.c: + wined3d: Mark textures dirty on UnLoad. + + * dlls/wined3d/basetexture.c, dlls/wined3d/cubetexture.c, + dlls/wined3d/texture.c, dlls/wined3d/volumetexture.c, + dlls/wined3d/wined3d_private.h: + wined3d: Move some UnLoad code to the base texture class. + + * dlls/wined3d/device.c: + wined3d: Destroy FBOs and reset pointers on Reset. + + * dlls/wined3d/surface.c: + wined3d: Unload implicit depth stencil buffers correctly. + We have to destroy potential fbo renderbuffers, and make sure the + texture is gone + + * dlls/wined3d/device.c: + wined3d: Update the auto depth stencil buffer size on reset. + + * dlls/wined3d/device.c: + wined3d: Beware of texture_rectangle NP2 support in Reset. + +2008-02-04 James Hawkins + + * dlls/msi/action.c, dlls/msi/tests/install.c: + msi: Fix handling of the NULL separator when writing registry values. + +2008-01-30 Aric Stewart + + * dlls/gdi32/freetype.c: + gdi32: Child fonts need to be scaled like their parent. With input from Dmitry + Timoshkov. + +2008-02-05 Francois Gouget + + * dlls/d3dx8/d3dx8_main.c, include/d3dx8core.h: + d3dx8: Fix the D3DXAssembleShaderFromFileA/W() prototypes. + + * include/Makefile.in, include/d3dx8.h, include/d3dx8core.h, + include/d3dx8mesh.h: + d3dx8: Add the d3dx8mesh.h header and move the relevant function declarations + there. + Include d3dx8mesh.h in d3dx8.h and add some commented out ones as reminders. + + * include/d3dx8core.h: + d3dx8: Make d3dx8core.h C++ compatible. + + * dlls/d3dx8/math.c, include/d3dx8math.h: + d3dx8: Fix the D3DXMatrixAffineTransformation() prototype. + + * include/d3dx8core.h: + d3dx8core.h: Remove some extraneous #include directives. + + * tools/winapi/win32.api: + winapi_check: Update win32.api for d3dx8.dll. + + * tools/winapi/win32.api: + winapi_check: Assorted win32.api updates. + + * tools/winapi/win32.api: + winapi_check: Update win32.api for acledit.dll, ctapi32.dll and inetcomm.dll. + + * dlls/msvcrt/msvcrt.spec: + msvcrt: __CxxDetectRethrow() and __CxxQueryExceptionSize() are implemented + now so export them. + +2008-02-04 Francois Gouget + + * dlls/winex11.drv/wintab.c: + winex11.drv: Add some API documentation stubs to make winapi_check happy. + + * dlls/ntdsapi/ntdsapi.c: + ntdsapi: Add an API documentation stub to make winapi_check happy. + + * dlls/mapi32/util.c: + mapi32: Add an API documentation stub to make winapi_check happy. + + * dlls/ddraw/tests/visual.c: + ddraw/tests: Fix compilation on systems that don't support nameless unions. + +2008-02-04 James Hawkins + + * dlls/msi/format.c, dlls/msi/tests/format.c: + msi: Reimplement MsiFormatRecord. + + * dlls/msi/tests/format.c: + msi: Add more tests for MsiFormatRecord. + +2008-02-04 Rob Shearman + + * dlls/rpcrt4/rpc_server.c: + rpcrt4: Fix potential memory leaks on error paths in RPCRT4_io_thread. + + * dlls/rpcrt4/rpc_message.c: + rpcrt4: Fix potential memory leaks in RPCRT4_Receive. + +2008-02-04 Andrew Talbot + + * dlls/wininet/ftp.c, dlls/wininet/http.c, dlls/wininet/internet.c, + dlls/wininet/urlcache.c, dlls/wininet/utility.c: + wininet: Remove unneeded casts. + + * dlls/winex11.drv/xfont.c: + winex11.drv: Remove unneeded casts. + +2008-02-04 Rob Shearman + + * dlls/ws2_32/socket.c: + ws2_32: Add a FIXME for WS_SIO_GET_EXTENSION_FUNCTION_POINTER in WSAIoctl. + + * server/named_pipe.c: + server: Always try return a named pipe server that is listening from + find_available_server. + We still fallback to an idle server, but this prevents a client from + connecting to a named pipe server that isn't listening. + + * dlls/ntdll/file.c: + ntdll: The FileMailslotSetInformation and FileCompletionInformation cases of + NtSetInformationFile don't need the fd. + So don't do an extra server call to get the fd to avoid a performance + penalty and to make these cases work when an fd isn't available. + +2008-02-04 James Hawkins + + * dlls/msi/msi.c, dlls/msi/tests/msi.c: + msi: Return ERROR_MORE_DATA if the size is too small. + + * dlls/msi/msi.c, dlls/msi/tests/msi.c: + msi: Return the string length even if the string is NULL. + + * dlls/msi/msi.c, dlls/msi/tests/msi.c: + msi: Leave room for the NULL terminator. + + * dlls/msi/msi.c, dlls/msi/tests/msi.c: + msi: Return ERROR_FILE_INVALID if the file has no version information. + + * dlls/msi/msi.c, dlls/msi/tests/msi.c: + msi: Return ERROR_INVALID_PARAMETER if a string pointer is non-NULL and the + size pointer is NULL. + + * dlls/msi/msi.c, dlls/msi/tests/msi.c: + msi: Translate ERROR_BAD_PATHNAME into ERROR_FILE_NOT_FOUND. + + * dlls/msi/msi.c, dlls/msi/tests/msi.c: + msi: Only convert output strings if the call succeeded. + + * dlls/msi/tests/Makefile.in, dlls/msi/tests/msi.c: + msi: Add tests for MsiGetFileVersion. + + * dlls/msi/streams.c: + msi: Implement the MSIMODIFY_ASSIGN action of MsiViewModify for the streams + table. + + * dlls/msi/tests/db.c: + msi: Add tests for using single quotes in an INSERT query. + + * dlls/version/info.c, dlls/version/tests/info.c: + version: Return ERROR_RESOURCE_DATA_NOT_FOUND if the file does not have + version information. + + * dlls/kernel32/tests/version.c: + kernel32: Factor out the VerifyVersionInfo tests into their own function. + +2008-02-03 Reece H. Dunn + + * dlls/gdiplus/tests/graphicspath.c: + gdiplus: Fix the bezier arc path test on all Windows platforms. + + * dlls/comctl32/trackbar.c: + comctl32: Proper fix redrawing the trackbar background with themes enabled. + +2008-02-01 Michael Stefaniuc + + * dlls/olecli32/olecli.h, dlls/olecli32/olecli16.c, + dlls/olecli32/olecli_main.c: + olecli: Remove duplicated typedefs/enums. + Use a local header file for them. + +2008-02-01 Stefan Leichter + + * dlls/advapi32/tests/service.c: + advapi32: Fix the failing QueryServiceConfig2 test on platforms win2k3 and vista. + +2008-01-30 Alistair Leslie-Hughes + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/stringformat.c: + gdiplus: Add GdipSetStringFormatFlags stub. + + * dlls/gdiplus/gdiplus.spec, dlls/gdiplus/pen.c, include/gdiplusenums.h: + gdiplus: Add GdipSetPenMode stub. + + * dlls/kernel32/kernel32.spec, dlls/kernel32/process.c: + kernel32: Add RegisterApplicationRestart stub. + +2008-01-28 Gerald Pfeifer + + * configure, configure.ac: + configure: Use GCC's -Wtype-limits if possible. + +2008-01-27 Eric Pouech + + * dlls/dbghelp/msc.c: + dbghelp: Fixed the types we want to load at first. + + * dlls/riched20/editor.h, dlls/riched20/richole.c, dlls/riched20/run.c: + riched20: Make use of the size info in REOBJECT if present. + + * dlls/riched20/editor.c: + riched20: Start implementing object reading out RTF stream. + + * dlls/riched20/editor.c, dlls/riched20/rtf.h: + riched20: Added support for image reading from RTF stream. + + * dlls/riched20/editor.c: + riched20: Support a couple of paragraphs attributes out of RTF stream reading. + + * dlls/riched20/richole.c: + riched20: Invert graphics when they are under the selection. + + * dlls/riched20/wrap.c: + riched20: Correctly handle the wrapping when graphics are used. + Get rid of infinite loops when run's width was larger than the global + available width. + + * dlls/riched20/richole.c: + riched20: Handle the zoom in OLE objects. + + * dlls/riched20/caret.c, dlls/riched20/editor.h, dlls/riched20/editstr.h, + dlls/riched20/list.c, dlls/riched20/paint.c, dlls/riched20/richole.c, + dlls/riched20/run.c, dlls/riched20/undo.c: + riched20: Start handling OLE objects inside richedit. + +2008-02-04 Alexandre Julliard + + * dlls/shell32/shfldr_unixfs.c: + shell32: Fix permissions of newly-created directories. + + * dlls/winex11.drv/bitmap.c: + winex11: Remove unneeded check on bitmap depth, screen bpp cannot be 15. + + * dlls/winex11.drv/dib.c, dlls/winex11.drv/x11drv.h, + dlls/winex11.drv/x11drv_main.c: + winex11: Abstract the depth->bpp conversion and use it in + X11DRV_DIB_CreateDIBFromPixmap. + +2008-02-02 Andrew Talbot + + * dlls/winex11.drv/bitblt.c, dlls/winex11.drv/clipboard.c, + dlls/winex11.drv/dib.c, dlls/winex11.drv/event.c, + dlls/winex11.drv/opengl.c, dlls/winex11.drv/wintab.c: + winex11.drv: Remove unneeded casts. + + * dlls/wineps.drv/driver.c, dlls/wineps.drv/type1afm.c: + wineps.drv: Remove unneeded casts. + + * dlls/winemp3.acm/interface.c, dlls/winemp3.acm/layer2.c: + winemp3.acm: Remove unneeded casts. + +2008-02-01 Eric Pouech + + * programs/winedbg/gdbproxy.c: + winedbg: Implemented the pXX request in gdb proxy. + +2008-02-02 Hans Leidekker + + * dlls/wininet/http.c, dlls/wininet/tests/http.c: + wininet: Add zero value content length header to POST requests only. + +2008-02-01 Hans Leidekker + + * dlls/wininet/http.c: + wininet: Send HTTP/1.1 requests by default. + + * dlls/wininet/http.c, dlls/wininet/tests/http.c: + wininet: Make sure not to overwrite any caller supplied authorization header. + +2008-01-31 Andre Wisplinghoff + + * programs/winecfg/libraries.c: + winecfg: Enable add button when choosing lib from combobox (Libraries tabsheet). + +2008-02-01 Alistair Leslie-Hughes + + * dlls/msxml3/tests/xmldoc.c, dlls/msxml3/xmldoc.c: + msxml3: Correct createElement return value for an invalid type. + + * dlls/msxml3/tests/domdoc.c: + msxml3: Corrected Entity Reference Test. + + * dlls/msxml3/element.c, dlls/msxml3/tests/domdoc.c: + msxml3: Validated attribute name. + +2008-02-01 Bang Jun-young + + * dlls/riched20/writer.c: + riched20: Include wine/port.h for vsnprintf(). + + * dlls/user32/menu.c, include/winuser.h: + user32: Fix EndMenu() to match the PSDK. + + * dlls/crypt32/decode.c, dlls/crypt32/encode.c: + crypt32: Include wine/port.h for snprintf(). + +2008-02-01 Jacek Caban + + * dlls/mshtml/Makefile.in, dlls/mshtml/mshtml_private.h, + dlls/mshtml/nsio.c: + mshtml: Update wine_url in nsIURI::SetPath. + +2008-01-31 Jacek Caban + + * dlls/urlmon/tests/url.c: + urlmon: Added more tests. + + * dlls/itss/tests/protocol.c: + itss: Added BINDF_NEEDFILE test. + + * dlls/urlmon/tests/protocol.c: + urlmon: Added more protocol tests. + + * dlls/urlmon/http.c: + urlmon: Correctly handle BINDF_NEEDFILE flag in http protocol. + + * dlls/urlmon/binding.c: + urlmon: Added support for binding to IID_IUnknown storage (cache file). + + * dlls/urlmon/binding.c: + urlmon: Added BINDSTATUS_CACHEFILENAMEAVAILABLE support. + + * dlls/urlmon/binding.c: + urlmon: Don't create stgmed_obj for binding to object. + + * dlls/urlmon/binding.c: + urlmon: Abstract ProtocolStream object. + + * dlls/urlmon/binding.c: + urlmon: Separate buffer from stream object. + + * dlls/mshtml/tests/protocol.c: + mshtml: Added more about protocol tests. + + * dlls/urlmon/binding.c: + urlmon: Return better error results. + + * dlls/urlmon/tests/url.c: + urlmon: Fixed tests. + + * dlls/urlmon/tests/misc.c, dlls/urlmon/urlmon.spec, + dlls/urlmon/urlmon_main.c, include/urlmon.idl: + urlmon: Added CopyStgMedium implementation. + +2008-01-31 Rob Shearman + + * dlls/comctl32/animate.c: + comctl32: Get the background colour in ANIMATE_PaintFrame, instead of just + in WM_PAINT. + This fixes the rendering of transparent animations when using a + background thread. + + * dlls/rpcrt4/tests/rpc.c: + rpcrt4: Fix memory leaks in the rpc tests. + + * dlls/wininet/http.c, dlls/wininet/tests/http.c: + wininet: HTTP_Connect should fail if a NULL or empty hostname is passed in. + Add tests for these circumstances. + + * dlls/ole32/Makefile.in, dlls/ole32/moniker.c, dlls/ole32/moniker.h, + dlls/ole32/oleproxy.c, dlls/ole32/pointermoniker.c, + dlls/ole32/regsvr.c, dlls/ole32/tests/moniker.c: + ole32: Add pointer moniker implementation. + + * dlls/ole32/tests/moniker.c: + ole32: Add tests for CreatePointerMoniker. + + * dlls/oleaut32/tests/safearray.c: + oleaut32: Fix some memory leaks in the safearray tests. + + * tools/wine.inf: + wine.inf: Make UI effects default to on. + This makes SPI_GETUIEFFECTS return TRUE by default. + + * dlls/advapi32/service.c: + advapi32: Fix the size calculation in StartServiceW. + Calculating an open-ended structure using sizeof doesn't yield an + accurate size because of alignment. + + * dlls/comctl32/animate.c: + comctl32: In certain circumstances, native comctl32's animation control accepts + negative start positions for the ACM_PLAY message. + These circumstances seems to be after a seek is performed, but we play + it safe and allow negative start positions to be treated as zero always. + + * dlls/oleaut32/olepicture.c: + oleaut32: Fix a leak of bmi in OLEPictureImpl_LoadGif. + + * dlls/oleaut32/tests/tmarshal.c: + oleaut32: Fix some reference count leaks in the tmarshal test. + + * dlls/rpcrt4/rpc_message.c: + rpcrt4: Fix some incorrect checks in RPCRT4_Receive. + + * dlls/oleaut32/tests/olefont.c: + oleaut32: Fix a memory leak in the olefont tests. + + * dlls/oleaut32/olefont.c: + oleaut32: Fix a leak of a typelib object in OLEFontImpl_GetTypeInfo. + + * dlls/ole32/moniker.c, dlls/ole32/ole32.spec: + ole32: Add a stub implementation of CreatePointerMoniker. + + * dlls/mapi32/mapi32.spec, dlls/mapi32/util.c: + mapi32: Add a stub implementation of HrQueryAllRows@24. + +2008-01-27 Eric Pouech + + * dlls/dbghelp/Makefile.in, dlls/dbghelp/minidump.c: + dbghelp: Store the PE version information in module block. + + * dlls/dbghelp/minidump.c: + dbghelp: Removed double assignment of checksum. + + * dlls/dbghelp/minidump.c: + dbghelp: Fixed the suspend count when creating a minidump in the middle of + an exception. + + * dlls/dbghelp/minidump.c: + dbghelp: Return the size of each directory instead of passing a pointer to it. + +2008-01-31 Michael Stefaniuc + + * dlls/user32/hook.c, dlls/user32/message.c, dlls/user32/user_private.h: + user32: Remove duplicated get_hook_proc() function. + +2008-01-31 Dmitry Timoshkov + + * dlls/kernel32/ne_module.c: + kernel32: LOADPARAMS16->showCmd can be NULL, do not crash in that case. + +2008-01-30 Rob Shearman + + * tools/widl/client.c, tools/widl/proxy.c, tools/widl/server.c, + tools/widl/typegen.c, tools/widl/typegen.h: + widl: Output code for initialising and freeing full pointer translation tables. + + * tools/widl/parser.l: + widl: Don't search for a import file name with a path in the include directories + for compatibility with MIDL. + +2008-01-29 Jacek Caban + + * tools/widl/write_msft.c: + widl: Ignore ATTR_LOCAL in create_msft_typeinfo. + + * dlls/urlmon/urlmon_main.c: + urlmon: Added comments about missing MIME filters. + + * dlls/hlink/hlink_main.c: + hlink: Don't prefer native version. + It's no longer a stub DLL. + + * dlls/hlink/extserv.c, dlls/hlink/hlink_main.c: + hlink: Added standard comments. + + * dlls/hlink/tests/hlink.c: + hlink: Added HlinkResolveMonikerForData tests. + + * dlls/hlink/hlink.spec, dlls/hlink/hlink_main.c: + hlink: Added HlinkResolveMonikerForData implementation. + + * dlls/hlink/tests/hlink.c: + hlink: Added HlinkParseDisplayName tests. + + * dlls/hlink/hlink.spec, dlls/hlink/hlink_main.c: + hlink: Added HlinkParseDisplayName implementation. + + * include/hlink.idl: + hlink.idl: Added more function declarations. + + * dlls/hlink/extserv.c: + hlink: Call AddRef of correct interface in ExtServUnk_QueryInterface. + + * dlls/urlmon/tests/misc.c: + urlmon: Added MkParseDisplayNameEx tests. + + * dlls/urlmon/session.c, dlls/urlmon/umon.c, dlls/urlmon/urlmon.spec, + dlls/urlmon/urlmon_main.h: + urlmon: Added HlinkParseDisplayNameEx implementation. + +2008-01-27 Paul Vriens + + * include/wintrust.h: + include/wintrust.h: Add missing members to CRYPT_PROVIDER_DATA struct (fixes + some wintrust tests on Windows). + +2008-01-26 Marcus Meissner + + * dlls/pdh/pdh_main.c: + pdh: Fixed wrong condition. + + * dlls/atl/atl_ax.c: + atl: Check for NULL. + + * programs/wordpad/registry.c: + wordpad: Remove condition that never triggers. + +2008-01-26 Francois Gouget + + * tools/winedump/lnk.c: + winedump: Add support for dumping SZ_LINK and SPECIAL_FOLDER data blocks. + + * tools/winedump/lnk.c: + winedump: Switch the block dumping code to be block-oriented, rather then flag + oriented, so it is resilient to order changes. + + * tools/winedump/lnk.c: + winedump: Dump the raw data when finding an unknown block in an lnk file. + + * tools/winedump/lnk.c: + winedump: Track unknown lnk flags and dump them. + + * tools/winedump/lnk.c: + winedump: Use the standard SLDF_XXX flag names instead of inventing new + ones. Add the missing flags. + +2008-01-26 Francois Gouget + + * dlls/user32/display.drv.spec: + user32: Fix a typo in the StretchDIBits stub name. + +2008-01-26 Francois Gouget + + * include/shlobj.h: + shell32: Add some SLDF_XXX values, EXP_PROPERTYSTORAGE, and + EXP_PROPERTYSTORAGE_SIG. + + * dlls/shell32/tests/shelllink.c: + shell32/tests: Fix a couple of copy/paste errors. + +2008-01-25 Gerald Pfeifer + + * dlls/d3d9/tests/visual.c: + d3d9: Fix the type of three loop variables. + +2008-01-25 Rob Shearman + + * dlls/oleaut32/tmarshal.c: + oleaut32: Fix big memory leak in xCall. + Call IRpcChannelBuffer_FreeBuffer to free the buffer and other resources + allocated by IRpcChannelBuffer_GetBuffer and IRpcChannelBuffer_SendReceive. + + * dlls/secur32/dispatcher.c: + secur32: Initialise more pointers in helper to NULL. + This is to avoid calling HeapFree on random pointers when + DeleteSecurityContext is called on a context that hasn't had a second + InitializeSecurityContext called on it, which would otherwise intialise + those pointers. + + * dlls/secur32/ntlm.c: + secur32: Try to retrive credentials by using the credential manager to retrieve + credentials saved for the target server in InitializeContextHandleW, if possible. + + * dlls/secur32/ntlm.c: + secur32: If using cached credentials failed in InitializeSecurityContext then + fail with SEC_E_NO_CREDENTIALS instead of carrying on with a blank password. + + * dlls/secur32/ntlm.c: + secur32: Move the detection of NULL credentials from AcquireCredentialsHandle + to InitializeSecurityContext. + Only use cached credentials if the credentials were NULL. Don't pass a + domain into ntlm_auth when using cached credentials as + ntlm_auth/winbindd should be able to figure that out. + +2008-01-25 Alexandre Julliard + + * ANNOUNCE, ChangeLog, VERSION, configure: + Release 0.9.54. + +---------------------------------------------------------------- 2008-01-25 Dmitry Timoshkov * dlls/winex11.drv/x11drv_main.c: diff --git a/VERSION b/VERSION index 30c5606f5ec..fcc5388c8b6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Wine version 0.9.54 +Wine version 0.9.55 diff --git a/configure b/configure index 443b48ab5cb..42034c64b3a 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 0.9.54. +# Generated by GNU Autoconf 2.61 for Wine 0.9.55. # # Report bugs to . # @@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='Wine' PACKAGE_TARNAME='wine' -PACKAGE_VERSION='0.9.54' -PACKAGE_STRING='Wine 0.9.54' +PACKAGE_VERSION='0.9.55' +PACKAGE_STRING='Wine 0.9.55' PACKAGE_BUGREPORT='wine-devel@winehq.org' ac_unique_file="server/atom.c" @@ -1291,7 +1291,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 0.9.54 to adapt to many kinds of systems. +\`configure' configures Wine 0.9.55 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1360,7 +1360,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Wine 0.9.54:";; + short | recursive ) echo "Configuration of Wine 0.9.55:";; esac cat <<\_ACEOF @@ -1486,7 +1486,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Wine configure 0.9.54 +Wine configure 0.9.55 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1500,7 +1500,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 0.9.54, which was +It was created by Wine $as_me 0.9.55, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -16098,6 +16098,64 @@ if test $ac_cv_cflags__Wwrite_strings = yes; then EXTRACFLAGS="$EXTRACFLAGS -Wwrite-strings" fi + { echo "$as_me:$LINENO: checking whether the compiler supports -Wtype-limits" >&5 +echo $ECHO_N "checking whether the compiler supports -Wtype-limits... $ECHO_C" >&6; } +if test "${ac_cv_cflags__Wtype_limits+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_wine_try_cflags_saved=$CFLAGS +CFLAGS="$CFLAGS -Wtype-limits" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + 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_cflags__Wtype_limits=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_cflags__Wtype_limits=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +CFLAGS=$ac_wine_try_cflags_saved +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cflags__Wtype_limits" >&5 +echo "${ECHO_T}$ac_cv_cflags__Wtype_limits" >&6; } +if test $ac_cv_cflags__Wtype_limits = yes; then + EXTRACFLAGS="$EXTRACFLAGS -Wtype-limits" +fi + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wpointer-arith -Werror" @@ -22269,7 +22327,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 0.9.54, which was +This file was extended by Wine $as_me 0.9.55, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -22322,7 +22380,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -Wine config.status 0.9.54 +Wine config.status 0.9.55 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 33852d79420..b6ee436b8b1 100644 --- a/configure.ac +++ b/configure.ac @@ -1222,6 +1222,7 @@ then WINE_TRY_CFLAGS([-fno-strict-aliasing]) WINE_TRY_CFLAGS([-Wdeclaration-after-statement]) WINE_TRY_CFLAGS([-Wwrite-strings]) + WINE_TRY_CFLAGS([-Wtype-limits]) dnl Check for noisy string.h saved_CFLAGS="$CFLAGS" diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index 7cfd9ea27bf..9f27c40ea2c 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -484,7 +484,7 @@ static BOOL service_send_start_message(HANDLE pipe, LPCWSTR *argv, DWORD argc) for (i=0; icmd = WINESERV_STARTINFO; ssi->size = len; @@ -497,7 +497,7 @@ static BOOL service_send_start_message(HANDLE pipe, LPCWSTR *argv, DWORD argc) } *p=0; - r = WriteFile(pipe, ssi, sizeof *ssi + (len-1)*sizeof(WCHAR), &count, NULL); + r = WriteFile(pipe, ssi, FIELD_OFFSET(service_start_info, str[len]), &count, NULL); if (r) { r = ReadFile(pipe, &result, sizeof result, &count, NULL); diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index 6b43cb347db..97b5a85c402 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -1812,8 +1812,10 @@ static void test_process_security(void) ok(CreateProcessA( NULL, buffer, &psa, NULL, FALSE, 0, NULL, NULL, &startup, &info ), "CreateProcess with err:%d\n", GetLastError()); TEST_GRANTED_ACCESS( info.hProcess, PROCESS_ALL_ACCESS ); - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); + winetest_wait_child_process( info.hProcess ); + CloseHandle( info.hProcess ); + CloseHandle( info.hThread ); CloseHandle( event ); HeapFree(GetProcessHeap(), 0, Acl); HeapFree(GetProcessHeap(), 0, SecurityDescriptor); diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index cf5b809d4ea..8c717157a79 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -938,7 +938,8 @@ static void test_queryconfig2(void) SetLastError(0xdeadbeef); ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),&needed); ok(!ret, "expected QueryServiceConfig2A to fail\n"); - ok(ERROR_INVALID_ADDRESS == GetLastError(), "expected error ERROR_INVALID_ADDRESS, got %d\n", GetLastError()); + ok((ERROR_INVALID_ADDRESS == GetLastError()) || (ERROR_INSUFFICIENT_BUFFER == GetLastError()), + "expected error ERROR_INVALID_ADDRESS or ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); SetLastError(0xdeadbeef); ret = pQueryServiceConfig2A(svc_handle, SERVICE_CONFIG_DESCRIPTION,NULL,sizeof(SERVICE_DESCRIPTIONA),NULL); diff --git a/dlls/atl/atl_ax.c b/dlls/atl/atl_ax.c index 64b338bf6a2..6ffccdec683 100644 --- a/dlls/atl/atl_ax.c +++ b/dlls/atl/atl_ax.c @@ -1026,7 +1026,8 @@ HRESULT WINAPI AtlAxCreateControlEx(LPCOLESTR lpszName, HWND hWnd, IUnknown_AddRef( pUnkControl ); } - IUnknown_Release( pUnkControl ); + if ( pUnkControl ) + IUnknown_Release( pUnkControl ); if ( pContainer ) IUnknown_Release( pContainer ); diff --git a/dlls/cabinet/tests/fdi.c b/dlls/cabinet/tests/fdi.c index 7c10b3d1663..18745f26061 100644 --- a/dlls/cabinet/tests/fdi.c +++ b/dlls/cabinet/tests/fdi.c @@ -92,10 +92,6 @@ static void test_FDICreate(void) HFDI hfdi; ERF erf; - erf.erfOper = 0xcafefeed; - erf.erfType = 0xdeadbabe; - erf.fError = 0xdecaface; - /* native crashes if pfnalloc is NULL */ /* FDICreate does not crash with a NULL pfnfree, @@ -104,6 +100,9 @@ static void test_FDICreate(void) if (0) { SetLastError(0xdeadbeef); + erf.erfOper = 0xcafefeed; + erf.erfType = 0xdeadbabe; + erf.fError = 0xdecaface; hfdi = FDICreate(fdi_alloc, NULL, fdi_open, fdi_read, fdi_write, fdi_close, fdi_seek, cpuUNKNOWN, &erf); @@ -118,99 +117,121 @@ static void test_FDICreate(void) } SetLastError(0xdeadbeef); + erf.erfOper = 0xcafefeed; + erf.erfType = 0xdeadbabe; + erf.fError = 0xdecaface; hfdi = FDICreate(fdi_alloc, fdi_free, NULL, fdi_read, fdi_write, fdi_close, fdi_seek, cpuUNKNOWN, &erf); ok(hfdi != NULL, "Expected non-NULL context\n"); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); - ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper); - ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType); - ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError); + ok((erf.erfOper == 0xcafefeed || erf.erfOper == 0 /* Vista */), "Expected 0xcafefeed or 0, got %d\n", erf.erfOper); + ok((erf.erfType == 0xdeadbabe || erf.erfType == 0 /* Vista */), "Expected 0xdeadbabe or 0, got %d\n", erf.erfType); + ok((erf.fError == 0xdecaface || erf.fError == 0 /* Vista */), "Expected 0xdecaface or 0, got %d\n", erf.fError); FDIDestroy(hfdi); SetLastError(0xdeadbeef); + erf.erfOper = 0xcafefeed; + erf.erfType = 0xdeadbabe; + erf.fError = 0xdecaface; hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, NULL, fdi_write, fdi_close, fdi_seek, cpuUNKNOWN, &erf); ok(hfdi != NULL, "Expected non-NULL context\n"); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); - ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper); - ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType); - ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError); + ok((erf.erfOper == 0xcafefeed || erf.erfOper == 0 /* Vista */), "Expected 0xcafefeed or 0, got %d\n", erf.erfOper); + ok((erf.erfType == 0xdeadbabe || erf.erfType == 0 /* Vista */), "Expected 0xdeadbabe or 0, got %d\n", erf.erfType); + ok((erf.fError == 0xdecaface || erf.fError == 0 /* Vista */), "Expected 0xdecaface or 0, got %d\n", erf.fError); FDIDestroy(hfdi); SetLastError(0xdeadbeef); + erf.erfOper = 0xcafefeed; + erf.erfType = 0xdeadbabe; + erf.fError = 0xdecaface; hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read, NULL, fdi_close, fdi_seek, cpuUNKNOWN, &erf); ok(hfdi != NULL, "Expected non-NULL context\n"); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); - ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper); - ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType); - ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError); + ok((erf.erfOper == 0xcafefeed || erf.erfOper == 0 /* Vista */), "Expected 0xcafefeed or 0, got %d\n", erf.erfOper); + ok((erf.erfType == 0xdeadbabe || erf.erfType == 0 /* Vista */), "Expected 0xdeadbabe or 0, got %d\n", erf.erfType); + ok((erf.fError == 0xdecaface || erf.fError == 0 /* Vista */), "Expected 0xdecaface or 0, got %d\n", erf.fError); FDIDestroy(hfdi); SetLastError(0xdeadbeef); + erf.erfOper = 0xcafefeed; + erf.erfType = 0xdeadbabe; + erf.fError = 0xdecaface; hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read, fdi_write, NULL, fdi_seek, cpuUNKNOWN, &erf); ok(hfdi != NULL, "Expected non-NULL context\n"); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); - ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper); - ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType); - ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError); + ok((erf.erfOper == 0xcafefeed || erf.erfOper == 0 /* Vista */), "Expected 0xcafefeed or 0, got %d\n", erf.erfOper); + ok((erf.erfType == 0xdeadbabe || erf.erfType == 0 /* Vista */), "Expected 0xdeadbabe or 0, got %d\n", erf.erfType); + ok((erf.fError == 0xdecaface || erf.fError == 0 /* Vista */), "Expected 0xdecaface or 0, got %d\n", erf.fError); FDIDestroy(hfdi); SetLastError(0xdeadbeef); + erf.erfOper = 0xcafefeed; + erf.erfType = 0xdeadbabe; + erf.fError = 0xdecaface; hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read, fdi_write, fdi_close, NULL, cpuUNKNOWN, &erf); ok(hfdi != NULL, "Expected non-NULL context\n"); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); - ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper); - ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType); - ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError); + ok((erf.erfOper == 0xcafefeed || erf.erfOper == 0 /* Vista */), "Expected 0xcafefeed or 0, got %d\n", erf.erfOper); + ok((erf.erfType == 0xdeadbabe || erf.erfType == 0 /* Vista */), "Expected 0xdeadbabe or 0, got %d\n", erf.erfType); + ok((erf.fError == 0xdecaface || erf.fError == 0 /* Vista */), "Expected 0xdecaface or 0, got %d\n", erf.fError); FDIDestroy(hfdi); SetLastError(0xdeadbeef); + erf.erfOper = 0xcafefeed; + erf.erfType = 0xdeadbabe; + erf.fError = 0xdecaface; hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read, fdi_write, fdi_close, fdi_seek, cpuUNKNOWN, NULL); - ok(hfdi != NULL, "Expected non-NULL context\n"); + /* XP sets hfdi to a non-NULL value, but Vista sets it to NULL! */ ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); - ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper); - ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType); - ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError); + /* NULL is passed to FDICreate instead of &erf, so don't retest the erf member values. */ FDIDestroy(hfdi); /* bad cpu type */ SetLastError(0xdeadbeef); + erf.erfOper = 0xcafefeed; + erf.erfType = 0xdeadbabe; + erf.fError = 0xdecaface; hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read, fdi_write, fdi_close, fdi_seek, 0xcafebabe, &erf); ok(hfdi != NULL, "Expected non-NULL context\n"); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); - ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper); - ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType); - ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError); + ok((erf.erfOper == 0xcafefeed || erf.erfOper == 0 /* Vista */), "Expected 0xcafefeed or 0, got %d\n", erf.erfOper); + ok((erf.erfType == 0xdeadbabe || erf.erfType == 0 /* Vista */), "Expected 0xdeadbabe or 0, got %d\n", erf.erfType); + ok((erf.fError == 0xdecaface || erf.fError == 0 /* Vista */), "Expected 0xdecaface or 0, got %d\n", erf.fError); FDIDestroy(hfdi); /* pfnalloc fails */ SetLastError(0xdeadbeef); + erf.erfOper = 0xcafefeed; + erf.erfType = 0xdeadbabe; + erf.fError = 0xdecaface; hfdi = FDICreate(fdi_alloc_bad, fdi_free, fdi_open, fdi_read, fdi_write, fdi_close, fdi_seek, cpuUNKNOWN, &erf); diff --git a/dlls/comctl32/animate.c b/dlls/comctl32/animate.c index d6c84daaadf..e0730f8aae1 100644 --- a/dlls/comctl32/animate.c +++ b/dlls/comctl32/animate.c @@ -345,10 +345,8 @@ static BOOL ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC) return TRUE; } -static BOOL ANIMATE_DrawFrame(ANIMATE_INFO *infoPtr) +static BOOL ANIMATE_DrawFrame(ANIMATE_INFO *infoPtr, HDC hDC) { - HDC hDC; - TRACE("Drawing frame %d (loop %d)\n", infoPtr->currFrame, infoPtr->nLoop); mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->currFrame], SEEK_SET); @@ -361,10 +359,7 @@ static BOOL ANIMATE_DrawFrame(ANIMATE_INFO *infoPtr) return FALSE; } - if ((hDC = GetDC(infoPtr->hwndSelf)) != 0) { - ANIMATE_PaintFrame(infoPtr, hDC); - ReleaseDC(infoPtr->hwndSelf, hDC); - } + ANIMATE_PaintFrame(infoPtr, hDC); if (infoPtr->currFrame++ >= infoPtr->nToFrame) { infoPtr->currFrame = infoPtr->nFromFrame; @@ -380,14 +375,20 @@ static BOOL ANIMATE_DrawFrame(ANIMATE_INFO *infoPtr) static LRESULT ANIMATE_Timer(ANIMATE_INFO *infoPtr) { - /* FIXME: we should pass the hDC instead of 0 to WM_CTLCOLORSTATIC */ - if (infoPtr->dwStyle & ACS_TRANSPARENT) - infoPtr->hbrushBG = (HBRUSH)SendMessageW(infoPtr->hwndNotify, - WM_CTLCOLORSTATIC, - 0, (LPARAM)infoPtr->hwndSelf); - EnterCriticalSection(&infoPtr->cs); - ANIMATE_DrawFrame(infoPtr); - LeaveCriticalSection(&infoPtr->cs); + HDC hDC; + + if ((hDC = GetDC(infoPtr->hwndSelf)) != 0) + { + if (infoPtr->dwStyle & ACS_TRANSPARENT) + infoPtr->hbrushBG = (HBRUSH)SendMessageW(infoPtr->hwndNotify, + WM_CTLCOLORSTATIC, + (WPARAM)hDC, (LPARAM)infoPtr->hwndSelf); + EnterCriticalSection(&infoPtr->cs); + ANIMATE_DrawFrame(infoPtr, hDC); + LeaveCriticalSection(&infoPtr->cs); + + ReleaseDC(infoPtr->hwndSelf, hDC); + } return 0; } @@ -400,12 +401,20 @@ static DWORD CALLBACK ANIMATE_AnimationThread(LPVOID ptr_) while(1) { + HDC hDC = GetDC(infoPtr->hwndSelf); + + if (infoPtr->dwStyle & ACS_TRANSPARENT) + infoPtr->hbrushBG = (HBRUSH)SendMessageW(infoPtr->hwndNotify, + WM_CTLCOLORSTATIC, + (WPARAM)hDC, (LPARAM)infoPtr->hwndSelf); EnterCriticalSection(&infoPtr->cs); - ANIMATE_DrawFrame(infoPtr); + ANIMATE_DrawFrame(infoPtr, hDC); timeout = infoPtr->mah.dwMicroSecPerFrame; event = infoPtr->hStopEvent; LeaveCriticalSection(&infoPtr->cs); + ReleaseDC(infoPtr->hwndSelf, hDC); + /* time is in microseconds, we should convert it to milliseconds */ if ((event == 0) || WaitForSingleObject( event, (timeout+500)/1000) == WAIT_OBJECT_0) break; @@ -434,6 +443,10 @@ static LRESULT ANIMATE_Play(ANIMATE_INFO *infoPtr, UINT cRepeat, WORD wFrom, WOR TRACE("(repeat=%d from=%d to=%d);\n", infoPtr->nLoop, infoPtr->nFromFrame, infoPtr->nToFrame); + if (infoPtr->nFromFrame >= infoPtr->mah.dwTotalFrames && + (SHORT)infoPtr->nFromFrame < 0) + infoPtr->nFromFrame = 0; + if (infoPtr->nFromFrame > infoPtr->nToFrame || infoPtr->nToFrame >= infoPtr->mah.dwTotalFrames) return FALSE; @@ -444,7 +457,18 @@ static LRESULT ANIMATE_Play(ANIMATE_INFO *infoPtr, UINT cRepeat, WORD wFrom, WOR * does it send a notification */ if (infoPtr->nFromFrame == infoPtr->nToFrame) { - ANIMATE_DrawFrame(infoPtr); + HDC hDC; + + if ((hDC = GetDC(infoPtr->hwndSelf)) != 0) + { + if (infoPtr->dwStyle & ACS_TRANSPARENT) + infoPtr->hbrushBG = (HBRUSH)SendMessageW(infoPtr->hwndNotify, + WM_CTLCOLORSTATIC, + (WPARAM)hDC, (LPARAM)infoPtr->hwndSelf); + ANIMATE_DrawFrame(infoPtr, hDC); + + ReleaseDC(infoPtr->hwndSelf, hDC); + } return TRUE; } @@ -925,11 +949,6 @@ static LRESULT WINAPI ANIMATE_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP return DefWindowProcW(hWnd, uMsg, wParam, lParam); } - if (infoPtr->dwStyle & ACS_TRANSPARENT) - infoPtr->hbrushBG = (HBRUSH)SendMessageW(infoPtr->hwndNotify, - WM_CTLCOLORSTATIC, - wParam, (LPARAM)infoPtr->hwndSelf); - if (wParam) { EnterCriticalSection(&infoPtr->cs); diff --git a/dlls/comctl32/comboex.c b/dlls/comctl32/comboex.c index 55e530866e2..379d9649379 100644 --- a/dlls/comctl32/comboex.c +++ b/dlls/comctl32/comboex.c @@ -412,8 +412,8 @@ static void COMBOEX_AdjustEditPos (COMBOEX_INFO *infoPtr) h = mysize.cy + 1; y = rect.bottom - h - 1; - TRACE("Combo client (%d,%d)-(%d,%d), setting Edit to (%d,%d)-(%d,%d)\n", - rect.left, rect.top, rect.right, rect.bottom, x, y, x + w, y + h); + TRACE("Combo client (%s), setting Edit to (%d,%d)-(%d,%d)\n", + wine_dbgstr_rect(&rect), x, y, x + w, y + h); SetWindowPos(infoPtr->hwndEdit, HWND_TOP, x, y, w, h, SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOZORDER); } @@ -952,12 +952,10 @@ static INT COMBOEX_SetItemHeight (COMBOEX_INFO const *infoPtr, INT index, UINT h height = cb_wrect.bottom-cb_wrect.top + cbx_wrect.bottom-cbx_wrect.top - (cbx_crect.bottom-cbx_crect.top); - TRACE("EX window=(%d,%d)-(%d,%d), client=(%d,%d)-(%d,%d)\n", - cbx_wrect.left, cbx_wrect.top, cbx_wrect.right, cbx_wrect.bottom, - cbx_crect.left, cbx_crect.top, cbx_crect.right, cbx_crect.bottom); - TRACE("CB window=(%d,%d)-(%d,%d), EX setting=(0,0)-(%d,%d)\n", - cb_wrect.left, cb_wrect.top, cb_wrect.right, cb_wrect.bottom, - cbx_wrect.right-cbx_wrect.left, height); + TRACE("EX window=(%s), client=(%s)\n", + wine_dbgstr_rect(&cbx_wrect), wine_dbgstr_rect(&cbx_crect)); + TRACE("CB window=(%s), EX setting=(0,0)-(%d,%d)\n", + wine_dbgstr_rect(&cbx_wrect), cbx_wrect.right-cbx_wrect.left, height); SetWindowPos (infoPtr->hwndSelf, HWND_TOP, 0, 0, cbx_wrect.right-cbx_wrect.left, height, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); @@ -1004,9 +1002,8 @@ static LRESULT COMBOEX_Create (HWND hwnd, CREATESTRUCTA const *cs) /* create combo box */ GetWindowRect(hwnd, &wnrc1); GetClientRect(hwnd, &clrc1); - TRACE("EX window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d)\n", - wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom, - clrc1.left, clrc1.top, clrc1.right, clrc1.bottom); + TRACE("EX window=(%s), client=(%s)\n", + wine_dbgstr_rect(&wnrc1), wine_dbgstr_rect(&clrc1)); /* Native version of ComboEx creates the ComboBox with DROPDOWNLIST */ /* specified. It then creates it's own version of the EDIT control */ @@ -1095,17 +1092,15 @@ static LRESULT COMBOEX_Create (HWND hwnd, CREATESTRUCTA const *cs) GetWindowRect(hwnd, &wnrc1); GetClientRect(hwnd, &clrc1); GetWindowRect(infoPtr->hwndCombo, &cmbwrc); - TRACE("EX window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d) CB wnd=(%d,%d)-(%d,%d)\n", - wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom, - clrc1.left, clrc1.top, clrc1.right, clrc1.bottom, - cmbwrc.left, cmbwrc.top, cmbwrc.right, cmbwrc.bottom); + TRACE("EX window=(%s) client=(%s) CB wnd=(%s)\n", + wine_dbgstr_rect(&wnrc1), wine_dbgstr_rect(&clrc1), + wine_dbgstr_rect(&cmbwrc)); SetWindowPos(infoPtr->hwndCombo, HWND_TOP, 0, 0, wnrc1.right-wnrc1.left, wnrc1.bottom-wnrc1.top, SWP_NOACTIVATE | SWP_NOREDRAW); GetWindowRect(infoPtr->hwndCombo, &cmbwrc); - TRACE("CB window=(%d,%d)-(%d,%d)\n", - cmbwrc.left, cmbwrc.top, cmbwrc.right, cmbwrc.bottom); + TRACE("CB window=(%s)\n", wine_dbgstr_rect(&cmbwrc)); SetWindowPos(hwnd, HWND_TOP, 0, 0, cmbwrc.right-cmbwrc.left, cmbwrc.bottom-cmbwrc.top, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); @@ -1354,10 +1349,8 @@ static LRESULT COMBOEX_DrawItem (COMBOEX_INFO *infoPtr, DRAWITEMSTRUCT const *di dis->CtlType, dis->CtlID); TRACE("itemID=0x%08x itemAction=0x%08x itemState=0x%08x\n", dis->itemID, dis->itemAction, dis->itemState); - TRACE("hWnd=%p hDC=%p (%d,%d)-(%d,%d) itemData=0x%08lx\n", - dis->hwndItem, dis->hDC, dis->rcItem.left, - dis->rcItem.top, dis->rcItem.right, dis->rcItem.bottom, - dis->itemData); + TRACE("hWnd=%p hDC=%p (%s) itemData=0x%08lx\n", + dis->hwndItem, dis->hDC, wine_dbgstr_rect(&dis->rcItem), dis->itemData); /* MSDN says: */ /* "itemID - Specifies the menu item identifier for a menu */ @@ -1374,9 +1367,8 @@ static LRESULT COMBOEX_DrawItem (COMBOEX_INFO *infoPtr, DRAWITEMSTRUCT const *di if ( ( (dis->itemAction & ODA_FOCUS) && (dis->itemState & ODS_SELECTED)) || ( (dis->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)) && (dis->itemState & ODS_FOCUS) ) ) { - TRACE("drawing item -1 special focus, rect=(%d,%d)-(%d,%d)\n", - dis->rcItem.left, dis->rcItem.top, - dis->rcItem.right, dis->rcItem.bottom); + TRACE("drawing item -1 special focus, rect=(%s)\n", + wine_dbgstr_rect(&dis->rcItem)); } else if ((dis->CtlType == ODT_COMBOBOX) && (dis->itemAction == ODA_DRAWENTIRE)) { @@ -1390,17 +1382,15 @@ static LRESULT COMBOEX_DrawItem (COMBOEX_INFO *infoPtr, DRAWITEMSTRUCT const *di edrc.left=edrc.top=edrc.right=edrc.bottom=-1; if (infoPtr->hwndEdit) GetWindowRect (infoPtr->hwndEdit, &edrc); - TRACE("window rects ex=(%d,%d)-(%d,%d), cb=(%d,%d)-(%d,%d), ed=(%d,%d)-(%d,%d)\n", - exrc.left, exrc.top, exrc.right, exrc.bottom, - cbrc.left, cbrc.top, cbrc.right, cbrc.bottom, - edrc.left, edrc.top, edrc.right, edrc.bottom); + TRACE("window rects ex=(%s), cb=(%s), ed=(%s)\n", + wine_dbgstr_rect(&exrc), wine_dbgstr_rect(&cbrc), + wine_dbgstr_rect(&edrc)); } } else { - ERR("NOT drawing item -1 special focus, rect=(%d,%d)-(%d,%d), action=%08x, state=%08x\n", - dis->rcItem.left, dis->rcItem.top, - dis->rcItem.right, dis->rcItem.bottom, - dis->itemAction, dis->itemState); + ERR("NOT drawing item -1 special focus, rect=(%s), action=%08x, state=%08x\n", + wine_dbgstr_rect(&dis->rcItem), + dis->itemAction, dis->itemState); return 0; } } @@ -1557,8 +1547,8 @@ static LRESULT COMBOEX_DrawItem (COMBOEX_INFO *infoPtr, DRAWITEMSTRUCT const *di rect.right = x + txtsize.cx; rect.top = dis->rcItem.top + 1; rect.bottom = dis->rcItem.bottom - 1; - TRACE("drawing item %d text, rect=(%d,%d)-(%d,%d)\n", - dis->itemID, rect.left, rect.top, rect.right, rect.bottom); + TRACE("drawing item %d text, rect=(%s)\n", + dis->itemID, wine_dbgstr_rect(&rect)); ExtTextOutW (dis->hDC, x, y, ETO_OPAQUE | ETO_CLIPPED, &rect, str, len, 0); SetBkColor (dis->hDC, bkc); @@ -1692,12 +1682,10 @@ static LRESULT COMBOEX_WindowPosChanging (COMBOEX_INFO *infoPtr, WINDOWPOS *wp) TRACE("winpos=(%d,%d %dx%d) flags=0x%08x\n", wp->x, wp->y, wp->cx, wp->cy, wp->flags); - TRACE("EX window=(%d,%d)-(%d,%d), client=(%d,%d)-(%d,%d)\n", - cbx_wrect.left, cbx_wrect.top, cbx_wrect.right, cbx_wrect.bottom, - cbx_crect.left, cbx_crect.top, cbx_crect.right, cbx_crect.bottom); - TRACE("CB window=(%d,%d)-(%d,%d), EX setting=(0,0)-(%d,%d)\n", - cb_wrect.left, cb_wrect.top, cb_wrect.right, cb_wrect.bottom, - width, cb_wrect.bottom-cb_wrect.top); + TRACE("EX window=(%s), client=(%s)\n", + wine_dbgstr_rect(&cbx_wrect), wine_dbgstr_rect(&cbx_crect)); + TRACE("CB window=(%s), EX setting=(0,0)-(%d,%d)\n", + wine_dbgstr_rect(&cbx_wrect), width, cb_wrect.bottom-cb_wrect.top); if (width) SetWindowPos (infoPtr->hwndCombo, HWND_TOP, 0, 0, width, @@ -1753,8 +1741,7 @@ COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) hDC = (HDC) wParam; obkc = SetBkColor (hDC, GetSysColor (COLOR_WINDOW)); GetClientRect (hwnd, &rect); - TRACE("erasing (%d,%d)-(%d,%d)\n", - rect.left, rect.top, rect.right, rect.bottom); + TRACE("erasing (%s)\n", wine_dbgstr_rect(&rect)); ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0); SetBkColor (hDC, obkc); return CallWindowProcW (infoPtr->prevEditWndProc, @@ -1957,8 +1944,7 @@ COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) hDC = (HDC) wParam; obkc = SetBkColor (hDC, GetSysColor (COLOR_WINDOW)); GetClientRect (hwnd, &rect); - TRACE("erasing (%d,%d)-(%d,%d)\n", - rect.left, rect.top, rect.right, rect.bottom); + TRACE("erasing (%s)\n", wine_dbgstr_rect(&rect)); ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0); SetBkColor (hDC, obkc); return CallWindowProcW (infoPtr->prevComboWndProc, diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c index 3c74033326c..16bf38a2024 100644 --- a/dlls/comctl32/listview.c +++ b/dlls/comctl32/listview.c @@ -7763,7 +7763,7 @@ static BOOL LISTVIEW_DrawTrackLine(const LISTVIEW_INFO *infoPtr) * RETURN: * None. */ -static CALLBACK VOID LISTVIEW_DelayedEditItem(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +static VOID CALLBACK LISTVIEW_DelayedEditItem(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { DELAYED_ITEM_EDIT *editItem = (DELAYED_ITEM_EDIT *)idEvent; LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongPtrW(hwnd, 0); diff --git a/dlls/comctl32/monthcal.c b/dlls/comctl32/monthcal.c index 1249f0f63cd..1c325de4508 100644 --- a/dlls/comctl32/monthcal.c +++ b/dlls/comctl32/monthcal.c @@ -344,7 +344,7 @@ static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, int day, int RECT r2; TRACE("%d %d %d\n",day, infoPtr->minSel.wDay, infoPtr->maxSel.wDay); - TRACE("%d %d %d %d\n", r.left, r.top, r.right, r.bottom); + TRACE("%s\n", wine_dbgstr_rect(&r)); oldCol = SetTextColor(hdc, infoPtr->monthbk); oldBk = SetBkColor(hdc, infoPtr->trailingtxt); hbr = GetSysColorBrush(COLOR_GRAYTEXT); diff --git a/dlls/comctl32/pager.c b/dlls/comctl32/pager.c index bcad6ea732a..2150c438d57 100644 --- a/dlls/comctl32/pager.c +++ b/dlls/comctl32/pager.c @@ -1008,9 +1008,8 @@ PAGER_MouseMove (PAGER_INFO* infoPtr, INT keys, INT x, INT y) /* If in one of the buttons the capture and draw buttons */ if (btnrect) { - TRACE("[%p] draw btn (%d,%d)-(%d,%d), Capture %s, style %08x\n", - infoPtr->hwndSelf, btnrect->left, btnrect->top, - btnrect->right, btnrect->bottom, + TRACE("[%p] draw btn (%s), Capture %s, style %08x\n", + infoPtr->hwndSelf, wine_dbgstr_rect(btnrect), (infoPtr->bCapture) ? "TRUE" : "FALSE", infoPtr->dwStyle); if (!infoPtr->bCapture) diff --git a/dlls/comctl32/propsheet.c b/dlls/comctl32/propsheet.c index f7e2cba6cc8..82d41cc90f3 100644 --- a/dlls/comctl32/propsheet.c +++ b/dlls/comctl32/propsheet.c @@ -709,8 +709,7 @@ static BOOL PROPSHEET_SizeMismatch(HWND hwndDlg, const PropSheetInfo* psInfo) * Original tab size. */ GetClientRect(hwndTabCtrl, &rcOrigTab); - TRACE("orig tab %d %d %d %d\n", rcOrigTab.left, rcOrigTab.top, - rcOrigTab.right, rcOrigTab.bottom); + TRACE("orig tab %s\n", wine_dbgstr_rect(&rcOrigTab)); /* * Biggest page size. @@ -721,8 +720,7 @@ static BOOL PROPSHEET_SizeMismatch(HWND hwndDlg, const PropSheetInfo* psInfo) rcPage.bottom = psInfo->height; MapDialogRect(hwndDlg, &rcPage); - TRACE("biggest page %d %d %d %d\n", rcPage.left, rcPage.top, - rcPage.right, rcPage.bottom); + TRACE("biggest page %s\n", wine_dbgstr_rect(&rcPage)); if ( (rcPage.right - rcPage.left) != (rcOrigTab.right - rcOrigTab.left) ) return TRUE; @@ -798,8 +796,7 @@ static BOOL PROPSHEET_AdjustSize(HWND hwndDlg, PropSheetInfo* psInfo) GetClientRect(hwndTabCtrl, &rc); - TRACE("tab client rc %d %d %d %d\n", - rc.left, rc.top, rc.right, rc.bottom); + TRACE("tab client rc %s\n", wine_dbgstr_rect(&rc)); rc.right += ((padding.x * 2) + tabOffsetX); rc.bottom += (buttonHeight + (3 * padding.y) + tabOffsetY); @@ -831,7 +828,7 @@ static BOOL PROPSHEET_AdjustSizeWizard(HWND hwndDlg, const PropSheetInfo* psInfo rc.bottom = psInfo->height; MapDialogRect(hwndDlg, &rc); - TRACE("Biggest page %d %d %d %d\n", rc.left, rc.top, rc.right, rc.bottom); + TRACE("Biggest page %s\n", wine_dbgstr_rect(&rc)); /* Add space for the buttons row */ GetWindowRect(hwndLine, &lineRect); @@ -2052,8 +2049,8 @@ static BOOL PROPSHEET_SetCurSel(HWND hwndDlg, * NOTE: The resizing happens every time the page is selected and * not only when it's created (some applications depend on it). */ PROPSHEET_GetPageRect(psInfo, hwndDlg, &rc, ppshpage); - TRACE("setting page %p, rc (%d,%d)-(%d,%d) w=%d, h=%d\n", - psInfo->proppage[index].hwndPage, rc.left, rc.top, rc.right, rc.bottom, + TRACE("setting page %p, rc (%s) w=%d, h=%d\n", + psInfo->proppage[index].hwndPage, wine_dbgstr_rect(&rc), rc.right - rc.left, rc.bottom - rc.top); SetWindowPos(psInfo->proppage[index].hwndPage, HWND_TOP, rc.left, rc.top, diff --git a/dlls/comctl32/rebar.c b/dlls/comctl32/rebar.c index 94e36f893c4..fa3033ae108 100644 --- a/dlls/comctl32/rebar.c +++ b/dlls/comctl32/rebar.c @@ -409,15 +409,12 @@ REBAR_DumpBand (const REBAR_INFO *iP) i, (pB->lpText) ? debugstr_w(pB->lpText) : "(null)"); TRACE("band # %u: lcx=%u, cxEffective=%u, lcy=%u\n", i, pB->lcx, pB->cxEffective, pB->lcy); - TRACE("band # %u: fStatus=%08x, fDraw=%08x, Band=(%d,%d)-(%d,%d), Grip=(%d,%d)-(%d,%d)\n", - i, pB->fStatus, pB->fDraw, - pB->rcBand.left, pB->rcBand.top, pB->rcBand.right, pB->rcBand.bottom, - pB->rcGripper.left, pB->rcGripper.top, pB->rcGripper.right, pB->rcGripper.bottom); - TRACE("band # %u: Img=(%d,%d)-(%d,%d), Txt=(%d,%d)-(%d,%d), Child=(%d,%d)-(%d,%d)\n", - i, - pB->rcCapImage.left, pB->rcCapImage.top, pB->rcCapImage.right, pB->rcCapImage.bottom, - pB->rcCapText.left, pB->rcCapText.top, pB->rcCapText.right, pB->rcCapText.bottom, - pB->rcChild.left, pB->rcChild.top, pB->rcChild.right, pB->rcChild.bottom); + TRACE("band # %u: fStatus=%08x, fDraw=%08x, Band=(%s), Grip=(%s)\n", + i, pB->fStatus, pB->fDraw, wine_dbgstr_rect(&pB->rcBand), + wine_dbgstr_rect(&pB->rcGripper)); + TRACE("band # %u: Img=(%s), Txt=(%s), Child=(%s)\n", + i, wine_dbgstr_rect(&pB->rcCapImage), + wine_dbgstr_rect(&pB->rcCapText), wine_dbgstr_rect(&pB->rcChild)); } } @@ -1018,11 +1015,9 @@ REBAR_MoveChildWindows (const REBAR_INFO *infoPtr, UINT start, UINT endplus) REBAR_Notify ((NMHDR *)&rbcz, infoPtr, RBN_CHILDSIZE); if (!EqualRect (&lpBand->rcChild, &rbcz.rcChild)) { TRACE("Child rect changed by NOTIFY for band %u\n", i); - TRACE(" from (%d,%d)-(%d,%d) to (%d,%d)-(%d,%d)\n", - lpBand->rcChild.left, lpBand->rcChild.top, - lpBand->rcChild.right, lpBand->rcChild.bottom, - rbcz.rcChild.left, rbcz.rcChild.top, - rbcz.rcChild.right, rbcz.rcChild.bottom); + TRACE(" from (%s) to (%s)\n", + wine_dbgstr_rect(&lpBand->rcChild), + wine_dbgstr_rect(&rbcz.rcChild)); lpBand->rcChild = rbcz.rcChild; /* *** ??? */ } @@ -1318,7 +1313,7 @@ REBAR_Layout(REBAR_INFO *infoPtr, const RECT *lpRect) GetClientRect(infoPtr->hwndSelf, &rcAdj); else GetClientRect(GetParent(infoPtr->hwndSelf), &rcAdj); - TRACE("adjustment rect is (%d,%d)-(%d,%d)\n", rcAdj.left, rcAdj.top, rcAdj.right, rcAdj.bottom); + TRACE("adjustment rect is (%s)\n", wine_dbgstr_rect(&rcAdj)); adjcx = get_rect_cx(infoPtr, &rcAdj); adjcy = get_rect_cy(infoPtr, &rcAdj); @@ -1685,9 +1680,8 @@ REBAR_InternalEraseBkGnd (const REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lPara else DrawEdge (hdc, &rcRowSep, EDGE_ETCHED, BF_BOTTOM); } - TRACE ("drawing band separator bottom (%d,%d)-(%d,%d)\n", - rcRowSep.left, rcRowSep.top, - rcRowSep.right, rcRowSep.bottom); + TRACE ("drawing band separator bottom (%s)\n", + wine_dbgstr_rect(&rcRowSep)); } } @@ -1711,8 +1705,8 @@ REBAR_InternalEraseBkGnd (const REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lPara else DrawEdge (hdc, &rcSep, EDGE_ETCHED, BF_RIGHT); } - TRACE("drawing band separator right (%d,%d)-(%d,%d)\n", - rcSep.left, rcSep.top, rcSep.right, rcSep.bottom); + TRACE("drawing band separator right (%s)\n", + wine_dbgstr_rect(&rcSep)); } /* draw the actual background */ @@ -2145,8 +2139,7 @@ REBAR_GetRect (const REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) /* For CCS_VERT the coordinates will be swapped - like on Windows */ CopyRect (lprc, &lpBand->rcBand); - TRACE("band %d, (%d,%d)-(%d,%d)\n", iBand, - lprc->left, lprc->top, lprc->right, lprc->bottom); + TRACE("band %d, (%s)\n", iBand, wine_dbgstr_rect(lprc)); return TRUE; } @@ -2689,16 +2682,13 @@ REBAR_SizeToRect (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) if (lpRect == NULL) return FALSE; - TRACE("[%d %d %d %d]\n", - lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + TRACE("[%s]\n", wine_dbgstr_rect(lpRect)); /* what is going on???? */ GetWindowRect(infoPtr->hwndSelf, &t1); - TRACE("window rect [%d %d %d %d]\n", - t1.left, t1.top, t1.right, t1.bottom); + TRACE("window rect [%s]\n", wine_dbgstr_rect(&t1)); GetClientRect(infoPtr->hwndSelf, &t1); - TRACE("client rect [%d %d %d %d]\n", - t1.left, t1.top, t1.right, t1.bottom); + TRACE("client rect [%s]\n", wine_dbgstr_rect(&t1)); /* force full _Layout processing */ REBAR_Layout(infoPtr, lpRect); @@ -2718,9 +2708,8 @@ REBAR_Create (REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) if (TRACE_ON(rebar)) { GetWindowRect(infoPtr->hwndSelf, &wnrc1); GetClientRect(infoPtr->hwndSelf, &clrc1); - TRACE("window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d) cs=(%d,%d %dx%d)\n", - wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom, - clrc1.left, clrc1.top, clrc1.right, clrc1.bottom, + TRACE("window=(%s) client=(%s) cs=(%d,%d %dx%d)\n", + wine_dbgstr_rect(&wnrc1), wine_dbgstr_rect(&clrc1), cs->x, cs->y, cs->cx, cs->cy); } @@ -3016,7 +3005,7 @@ REBAR_NCCalcSize (const REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) /* FIXME: should use GetThemeInt */ rect->top = min(rect->top + 1, rect->bottom); } - TRACE("new client=(%d,%d)-(%d,%d)\n", rect->left, rect->top, rect->right, rect->bottom); + TRACE("new client=(%s)\n", wine_dbgstr_rect(rect)); return 0; } @@ -3038,9 +3027,8 @@ REBAR_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam) if (TRACE_ON(rebar)) { GetWindowRect(hwnd, &wnrc1); GetClientRect(hwnd, &clrc1); - TRACE("window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d) cs=(%d,%d %dx%d)\n", - wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom, - clrc1.left, clrc1.top, clrc1.right, clrc1.bottom, + TRACE("window=(%s) client=(%s) cs=(%d,%d %dx%d)\n", + wine_dbgstr_rect(&wnrc1), wine_dbgstr_rect(&clrc1), cs->x, cs->y, cs->cx, cs->cy); } @@ -3167,9 +3155,7 @@ REBAR_NCPaint (const REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) return 0; GetWindowRect (infoPtr->hwndSelf, &rcWindow); OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top); - TRACE("rect (%d,%d)-(%d,%d)\n", - rcWindow.left, rcWindow.top, - rcWindow.right, rcWindow.bottom); + TRACE("rect (%s)\n", wine_dbgstr_rect(&rcWindow)); DrawEdge (hdc, &rcWindow, EDGE_ETCHED, BF_RECT); ReleaseDC( infoPtr->hwndSelf, hdc ); } @@ -3180,9 +3166,7 @@ REBAR_NCPaint (const REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) return 0; GetWindowRect (infoPtr->hwndSelf, &rcWindow); OffsetRect (&rcWindow, -rcWindow.left, -rcWindow.top); - TRACE("rect (%d,%d)-(%d,%d)\n", - rcWindow.left, rcWindow.top, - rcWindow.right, rcWindow.bottom); + TRACE("rect (%s)\n", wine_dbgstr_rect(&rcWindow)); DrawThemeEdge (theme, hdc, 0, 0, &rcWindow, BDR_RAISEDINNER, BF_TOP, NULL); ReleaseDC( infoPtr->hwndSelf, hdc ); } @@ -3220,10 +3204,8 @@ REBAR_Paint (const REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) GetClientRect(infoPtr->hwndSelf, &rc); hdc = wParam==0 ? BeginPaint (infoPtr->hwndSelf, &ps) : (HDC)wParam; - TRACE("painting (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", - ps.rcPaint.left, ps.rcPaint.top, - ps.rcPaint.right, ps.rcPaint.bottom, - rc.left, rc.top, rc.right, rc.bottom); + TRACE("painting (%s) client (%s)\n", + wine_dbgstr_rect(&ps.rcPaint), wine_dbgstr_rect(&rc)); if (ps.fErase) { /* Erase area of paint if requested */ @@ -3384,8 +3366,7 @@ REBAR_WindowPosChanged (const REBAR_INFO *infoPtr, WPARAM wParam, LPARAM lParam) ret = DefWindowProcW(infoPtr->hwndSelf, WM_WINDOWPOSCHANGED, wParam, lParam); GetWindowRect(infoPtr->hwndSelf, &rc); - TRACE("hwnd %p new pos (%d,%d)-(%d,%d)\n", - infoPtr->hwndSelf, rc.left, rc.top, rc.right, rc.bottom); + TRACE("hwnd %p new pos (%s)\n", infoPtr->hwndSelf, wine_dbgstr_rect(&rc)); return ret; } diff --git a/dlls/comctl32/status.c b/dlls/comctl32/status.c index 7ee11cbe759..2551e0a4cb9 100644 --- a/dlls/comctl32/status.c +++ b/dlls/comctl32/status.c @@ -114,8 +114,8 @@ STATUSBAR_DrawSizeGrip (HTHEME theme, HDC hdc, LPRECT lpRect) POINT pt; INT i; - TRACE("draw size grip %d,%d - %d,%d\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); - + TRACE("draw size grip %s\n", wine_dbgstr_rect(lpRect)); + if (theme) { RECT gripperRect; @@ -175,7 +175,7 @@ STATUSBAR_DrawPart (const STATUS_INFO *infoPtr, HDC hdc, const STATUSWINDOWPART HTHEME theme = GetWindowTheme (infoPtr->Self); int themePart = SP_PANE; - TRACE("part bound %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom); + TRACE("part bound %s\n", wine_dbgstr_rect(&r)); if (part->style & SBT_POPOUT) border = BDR_RAISEDOUTER; else if (part->style & SBT_NOBORDERS) @@ -333,7 +333,7 @@ STATUSBAR_SetPartBounds (STATUS_INFO *infoPtr) /* get our window size */ GetClientRect (infoPtr->Self, &rect); - TRACE("client wnd size is %d,%d - %d,%d\n", rect.left, rect.top, rect.right, rect.bottom); + TRACE("client wnd size is %s\n", wine_dbgstr_rect(&rect)); rect.left += infoPtr->horizontalBorder; rect.top += infoPtr->verticalBorder; diff --git a/dlls/comctl32/tab.c b/dlls/comctl32/tab.c index 92c92685cdd..4b1673a6a87 100644 --- a/dlls/comctl32/tab.c +++ b/dlls/comctl32/tab.c @@ -414,9 +414,8 @@ static BOOL TAB_InternalGetItemRect( SELECTED_TAB_OFFSET, 0); } - TRACE("item %d tab h=%d, rect=(%d,%d)-(%d,%d)\n", - itemIndex, infoPtr->tabHeight, - itemRect->left, itemRect->top, itemRect->right, itemRect->bottom); + TRACE("item %d tab h=%d, rect=(%s)\n", + itemIndex, infoPtr->tabHeight, wine_dbgstr_rect(itemRect)); /* Now, calculate the position of the item as if it were selected. */ if (selectedRect!=NULL) @@ -529,9 +528,7 @@ static void TAB_FocusChanging(const TAB_INFO *infoPtr) */ if (isVisible) { - TRACE("invalidate (%d,%d)-(%d,%d)\n", - selectedRect.left,selectedRect.top, - selectedRect.right,selectedRect.bottom); + TRACE("invalidate (%s)\n", wine_dbgstr_rect(&selectedRect)); InvalidateRect(infoPtr->hwnd, &selectedRect, TRUE); } } @@ -864,7 +861,8 @@ static LRESULT TAB_AdjustRect(const TAB_INFO *infoPtr, WPARAM fLarger, LPRECT pr DWORD lStyle = GetWindowLongW(infoPtr->hwnd, GWL_STYLE); LONG *iRightBottom, *iLeftTop; - TRACE ("hwnd=%p fLarger=%ld (%d,%d)-(%d,%d)\n", infoPtr->hwnd, fLarger, prc->left, prc->top, prc->right, prc->bottom); + TRACE ("hwnd=%p fLarger=%ld (%s)\n", infoPtr->hwnd, fLarger, + wine_dbgstr_rect(prc)); if(lStyle & TCS_VERTICAL) { @@ -1217,8 +1215,7 @@ static void TAB_SetItemBounds (TAB_INFO *infoPtr) curr->rect.bottom = 0; curr->rect.top = curItemRowCount - 1; - TRACE("Rect: T %i, L %i, B %i, R %i\n", curr->rect.top, - curr->rect.left, curr->rect.bottom, curr->rect.right); + TRACE("Rect: %s\n", wine_dbgstr_rect(&curr->rect)); /* * The leftmost position of the next item is the rightmost position @@ -1598,8 +1595,7 @@ TAB_DrawItemInterior(const TAB_INFO *infoPtr, HDC hdc, INT iItem, RECT *drawRect } } } - TRACE("drawRect=(%d,%d)-(%d,%d)\n", - drawRect->left, drawRect->top, drawRect->right, drawRect->bottom); + TRACE("drawRect=(%s)\n", wine_dbgstr_rect(drawRect)); /* Clear interior */ TAB_EraseTabInterior (infoPtr, hdc, iItem, drawRect); @@ -1742,10 +1738,9 @@ TAB_DrawItemInterior(const TAB_INFO *infoPtr, HDC hdc, INT iItem, RECT *drawRect if (center_offset_v < 0) center_offset_v = 0; - TRACE("for <%s>, c_o_h=%d, c_o_v=%d, draw=(%d,%d)-(%d,%d), textlen=%d\n", + TRACE("for <%s>, c_o_h=%d, c_o_v=%d, draw=(%s), textlen=%d\n", debugstr_w(item->pszText), center_offset_h, center_offset_v, - drawRect->left, drawRect->top, drawRect->right, drawRect->bottom, - (rcText.right-rcText.left)); + wine_dbgstr_rect(drawRect), (rcText.right-rcText.left)); if((lStyle & TCS_VERTICAL) && (lStyle & TCS_BOTTOM)) { @@ -1873,10 +1868,9 @@ TAB_DrawItemInterior(const TAB_INFO *infoPtr, HDC hdc, INT iItem, RECT *drawRect } else { - TRACE("for <%s>, c_o_h=%d, c_o_v=%d, draw=(%d,%d)-(%d,%d), textlen=%d\n", + TRACE("for <%s>, c_o_h=%d, c_o_v=%d, draw=(%s), textlen=%d\n", debugstr_w(item->pszText), center_offset_h, center_offset_v, - drawRect->left, drawRect->top, drawRect->right, drawRect->bottom, - (rcText.right-rcText.left)); + wine_dbgstr_rect(drawRect), (rcText.right-rcText.left)); if (item->pszText) { DrawTextW @@ -2061,10 +2055,8 @@ static void TAB_DrawItem(const TAB_INFO *infoPtr, HDC hdc, INT iItem) /* Adjust both rectangles to match native */ r.left += (1-ZZ); - TRACE(" item=%d, fill=(%d,%d)-(%d,%d), edge=(%d,%d)-(%d,%d)\n", - iItem, - fillRect.left,fillRect.top,fillRect.right,fillRect.bottom, - r.left,r.top,r.right,r.bottom); + TRACE(" item=%d, fill=(%s), edge=(%s)\n", + iItem, wine_dbgstr_rect(&fillRect), wine_dbgstr_rect(&r)); /* Clear interior */ SetBkColor(hdc, bkgnd); @@ -2102,10 +2094,8 @@ static void TAB_DrawItem(const TAB_INFO *infoPtr, HDC hdc, INT iItem) } else { - TRACE(" item=%d, fill=(%d,%d)-(%d,%d), edge=(%d,%d)-(%d,%d)\n", - iItem, - fillRect.left,fillRect.top,fillRect.right,fillRect.bottom, - r.left,r.top,r.right,r.bottom); + TRACE(" item=%d, fill=(%s), edge=(%s)\n", + iItem, wine_dbgstr_rect(&fillRect), wine_dbgstr_rect(&r)); /* Clear interior */ SetBkColor(hdc, bkgnd); @@ -2156,10 +2146,8 @@ static void TAB_DrawItem(const TAB_INFO *infoPtr, HDC hdc, INT iItem) r.top -= 1; } - TRACE(" item=%d, fill=(%d,%d)-(%d,%d), edge=(%d,%d)-(%d,%d)\n", - iItem, - fillRect.left,fillRect.top,fillRect.right,fillRect.bottom, - r.left,r.top,r.right,r.bottom); + TRACE(" item=%d, fill=(%s), edge=(%s)\n", + iItem, wine_dbgstr_rect(&fillRect), wine_dbgstr_rect(&r)); /* Clear interior */ SetBkColor(hdc, bkgnd); @@ -2210,10 +2198,8 @@ static void TAB_DrawItem(const TAB_INFO *infoPtr, HDC hdc, INT iItem) r.bottom += 2; } - TRACE(" item=%d, fill=(%d,%d)-(%d,%d), edge=(%d,%d)-(%d,%d)\n", - iItem, - fillRect.left,fillRect.top,fillRect.right,fillRect.bottom, - r.left,r.top,r.right,r.bottom); + TRACE(" item=%d, fill=(%s), edge=(%s)\n", + iItem, wine_dbgstr_rect(&fillRect), wine_dbgstr_rect(&r)); /* Clear interior */ SetBkColor(hdc, bkgnd); @@ -2281,8 +2267,7 @@ static void TAB_DrawBorder(const TAB_INFO *infoPtr, HDC hdc) rect.top += infoPtr->tabHeight * infoPtr->uNumRows + CONTROL_BORDER_SIZEX; } - TRACE("border=(%d,%d)-(%d,%d)\n", - rect.left, rect.top, rect.right, rect.bottom); + TRACE("border=(%s)\n", wine_dbgstr_rect(&rect)); if (theme) DrawThemeBackground (theme, hdc, TABP_PANE, 0, &rect, NULL); @@ -2517,11 +2502,9 @@ static void TAB_InvalidateTabArea(const TAB_INFO *infoPtr) else rInvalidate.right = clientRect.right - r.left; } - - TRACE("invalidate (%d,%d)-(%d,%d)\n", - rInvalidate.left, rInvalidate.top, - rInvalidate.right, rInvalidate.bottom); - + + TRACE("invalidate (%s)\n", wine_dbgstr_rect(&rInvalidate)); + InvalidateRect(infoPtr->hwnd, &rInvalidate, TRUE); } @@ -2535,9 +2518,7 @@ static inline LRESULT TAB_Paint (TAB_INFO *infoPtr, HDC hdcPaint) else { hdc = BeginPaint (infoPtr->hwnd, &ps); - TRACE("erase %d, rect=(%d,%d)-(%d,%d)\n", - ps.fErase, - ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right,ps.rcPaint.bottom); + TRACE("erase %d, rect=(%s)\n", ps.fErase, wine_dbgstr_rect(&ps.rcPaint)); } TAB_Refresh (infoPtr, hdc); @@ -2557,8 +2538,7 @@ TAB_InsertItemT (TAB_INFO *infoPtr, WPARAM wParam, LPARAM lParam, BOOL bUnicode) RECT rect; GetClientRect (infoPtr->hwnd, &rect); - TRACE("Rect: %p T %i, L %i, B %i, R %i\n", infoPtr->hwnd, - rect.top, rect.left, rect.bottom, rect.right); + TRACE("Rect: %p %s\n", infoPtr->hwnd, wine_dbgstr_rect(&rect)); pti = (TCITEMW *)lParam; iItem = (INT)wParam; diff --git a/dlls/comctl32/tests/comboex.c b/dlls/comctl32/tests/comboex.c index f3f46b3da36..ad58643f648 100644 --- a/dlls/comctl32/tests/comboex.c +++ b/dlls/comctl32/tests/comboex.c @@ -187,10 +187,23 @@ static LRESULT CALLBACK ComboExTestWndProc(HWND hWnd, UINT msg, WPARAM wParam, L return 0L; } -static void init(void) { +static int init(void) +{ + HMODULE hComctl32; + BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*); WNDCLASSA wc; - - InitCommonControls(); + INITCOMMONCONTROLSEX iccex; + + hComctl32 = GetModuleHandleA("comctl32.dll"); + pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx"); + if (!pInitCommonControlsEx) + { + skip("InitCommonControlsEx() is missing. Skipping the tests\n"); + return 0; + } + iccex.dwSize = sizeof(iccex); + iccex.dwICC = ICC_USEREX_CLASSES; + pInitCommonControlsEx(&iccex); wc.style = CS_HREDRAW | CS_VREDRAW; wc.cbClsExtra = 0; @@ -209,7 +222,7 @@ static void init(void) { assert(hComboExParentWnd != NULL); hMainHinst = GetModuleHandleA(NULL); - + return 1; } static void cleanup(void) @@ -227,7 +240,8 @@ static void cleanup(void) START_TEST(comboex) { - init(); + if (!init()) + return; test_comboboxex(); diff --git a/dlls/comctl32/tests/datetime.c b/dlls/comctl32/tests/datetime.c index d13abc6454b..76fdcccfab3 100644 --- a/dlls/comctl32/tests/datetime.c +++ b/dlls/comctl32/tests/datetime.c @@ -112,6 +112,7 @@ static const struct message test_dtm_set_range_swap_min_max_seq[] = { static const struct message test_dtm_set_and_get_system_time_seq[] = { { DTM_SETSYSTEMTIME, sent|wparam, 0x00000001 }, + { 0x0090, sent|optional }, /* Vista */ { WM_DESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 }, { WM_NCDESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 }, { DTM_SETSYSTEMTIME, sent|wparam, 0x00000001 }, @@ -125,6 +126,7 @@ static const struct message test_dtm_set_and_get_system_time_seq[] = { }; static const struct message destroy_window_seq[] = { + { 0x0090, sent|optional }, /* Vista */ { WM_DESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 }, { WM_NCDESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 }, { 0 } @@ -560,7 +562,21 @@ static void test_datetime_control(void) START_TEST(datetime) { - InitCommonControls(); + HMODULE hComctl32; + BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*); + INITCOMMONCONTROLSEX iccex; + + hComctl32 = GetModuleHandleA("comctl32.dll"); + pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx"); + if (!pInitCommonControlsEx) + { + skip("InitCommonControlsEx() is missing. Skipping the tests\n"); + return; + } + iccex.dwSize = sizeof(iccex); + iccex.dwICC = ICC_DATE_CLASSES; + pInitCommonControlsEx(&iccex); + init_msg_sequences(sequences, NUM_MSG_SEQUENCES); test_datetime_control(); diff --git a/dlls/comctl32/tests/header.c b/dlls/comctl32/tests/header.c index 884d4d527ce..6f8b46250f8 100644 --- a/dlls/comctl32/tests/header.c +++ b/dlls/comctl32/tests/header.c @@ -1480,10 +1480,24 @@ static LRESULT CALLBACK HeaderTestWndProc(HWND hWnd, UINT msg, WPARAM wParam, LP return 0L; } -static void init(void) { +static int init(void) +{ + HMODULE hComctl32; + BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*); WNDCLASSA wc; + INITCOMMONCONTROLSEX iccex; + + hComctl32 = GetModuleHandleA("comctl32.dll"); + pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx"); + if (!pInitCommonControlsEx) + { + skip("InitCommonControlsEx() is missing. Skipping the tests\n"); + return 0; + } - InitCommonControls(); + iccex.dwSize = sizeof(iccex); + iccex.dwICC = ICC_USEREX_CLASSES; + pInitCommonControlsEx(&iccex); wc.style = CS_HREDRAW | CS_VREDRAW; wc.cbClsExtra = 0; @@ -1503,13 +1517,15 @@ static void init(void) { NULL, NULL, GetModuleHandleA(NULL), 0); assert(hHeaderParentWnd != NULL); ShowWindow(hHeaderParentWnd, SW_SHOW); + return 1; } START_TEST(header) { HWND parent_hwnd; - init(); + if (!init()) + return; test_header_control(); test_header_order(); diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c index 30a81a8948f..6e6f535fba1 100644 --- a/dlls/comctl32/tests/listview.c +++ b/dlls/comctl32/tests/listview.c @@ -1040,7 +1040,20 @@ static void test_item_position(void) START_TEST(listview) { - InitCommonControls(); + HMODULE hComctl32; + BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*); + + hComctl32 = GetModuleHandleA("comctl32.dll"); + pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx"); + if (pInitCommonControlsEx) + { + INITCOMMONCONTROLSEX iccex; + iccex.dwSize = sizeof(iccex); + iccex.dwICC = ICC_LISTVIEW_CLASSES; + pInitCommonControlsEx(&iccex); + } + else + InitCommonControls(); init_msg_sequences(sequences, NUM_MSG_SEQUENCES); diff --git a/dlls/comctl32/tests/monthcal.c b/dlls/comctl32/tests/monthcal.c index 7fe2bd761c7..c056ede5679 100644 --- a/dlls/comctl32/tests/monthcal.c +++ b/dlls/comctl32/tests/monthcal.c @@ -280,6 +280,7 @@ static const struct message destroy_monthcal_parent_msgs_seq[] = { /* expected message sequence for child*/ static const struct message destroy_monthcal_child_msgs_seq[] = { + { 0x0090, sent|optional }, /* Vista */ { WM_SHOWWINDOW, sent|wparam|lparam, 0, 0}, { WM_WINDOWPOSCHANGING, sent|wparam, 0}, { WM_WINDOWPOSCHANGED, sent|wparam, 0}, @@ -289,6 +290,7 @@ static const struct message destroy_monthcal_child_msgs_seq[] = { }; static const struct message destroy_monthcal_multi_sel_style_seq[] = { + { 0x0090, sent|optional }, /* Vista */ { WM_DESTROY, sent|wparam|lparam, 0, 0}, { WM_NCDESTROY, sent|wparam|lparam, 0, 0}, { 0 } @@ -296,6 +298,7 @@ static const struct message destroy_monthcal_multi_sel_style_seq[] = { /* expected message sequence for parent window*/ static const struct message destroy_parent_seq[] = { + { 0x0090, sent|optional }, /* Vista */ { WM_WINDOWPOSCHANGING, sent|wparam, 0}, { WM_WINDOWPOSCHANGED, sent|wparam, 0}, { WM_NCACTIVATE, sent|wparam|lparam, 0, 0}, @@ -315,7 +318,6 @@ static void test_monthcal(void) SYSTEMTIME st[2], st1[2]; int res, month_range; - InitCommonControls(); hwnd = CreateWindowA(MONTHCAL_CLASSA, "MonthCal", WS_POPUP | WS_VISIBLE, CW_USEDEFAULT, 0, 300, 300, 0, 0, NULL, NULL); ok(hwnd != NULL, "Failed to create MonthCal\n"); @@ -478,8 +480,6 @@ static HWND create_monthcal_control(DWORD style, HWND parent_window) struct subclass_info *info; HWND hwnd; - InitCommonControls(); - info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info)); if (!info) return NULL; @@ -1109,7 +1109,22 @@ static void test_monthcal_MaxSelDay(HWND hwnd) START_TEST(monthcal) { + HMODULE hComctl32; + BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*); + INITCOMMONCONTROLSEX iccex; HWND hwnd, parent_wnd; + + hComctl32 = GetModuleHandleA("comctl32.dll"); + pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx"); + if (!pInitCommonControlsEx) + { + skip("InitCommonControlsEx() is missing. Skipping the tests\n"); + return; + } + iccex.dwSize = sizeof(iccex); + iccex.dwICC = ICC_DATE_CLASSES; + pInitCommonControlsEx(&iccex); + test_monthcal(); init_msg_sequences(sequences, NUM_MSG_SEQUENCES); diff --git a/dlls/comctl32/tests/progress.c b/dlls/comctl32/tests/progress.c index 2716f3356b4..10bbbef8a28 100644 --- a/dlls/comctl32/tests/progress.c +++ b/dlls/comctl32/tests/progress.c @@ -90,10 +90,22 @@ static void update_window(HWND hWnd) static void init(void) { + HMODULE hComctl32; + BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*); WNDCLASSA wc; RECT rect; - InitCommonControls(); + hComctl32 = GetModuleHandleA("comctl32.dll"); + pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx"); + if (pInitCommonControlsEx) + { + INITCOMMONCONTROLSEX iccex; + iccex.dwSize = sizeof(iccex); + iccex.dwICC = ICC_PROGRESS_CLASS; + pInitCommonControlsEx(&iccex); + } + else + InitCommonControls(); wc.style = CS_HREDRAW | CS_VREDRAW; wc.cbClsExtra = 0; diff --git a/dlls/comctl32/tests/rebar.c b/dlls/comctl32/tests/rebar.c index 6bebeb770a4..1de9cd2a7a7 100644 --- a/dlls/comctl32/tests/rebar.c +++ b/dlls/comctl32/tests/rebar.c @@ -786,11 +786,23 @@ static void bandinfo_test(void) START_TEST(rebar) { + HMODULE hComctl32; + BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*); + INITCOMMONCONTROLSEX iccex; WNDCLASSA wc; MSG msg; RECT rc; - InitCommonControls(); + hComctl32 = GetModuleHandleA("comctl32.dll"); + pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx"); + if (!pInitCommonControlsEx) + { + skip("InitCommonControlsEx() is missing. Skipping the tests\n"); + return; + } + iccex.dwSize = sizeof(iccex); + iccex.dwICC = ICC_COOL_CLASSES; + pInitCommonControlsEx(&iccex); wc.style = CS_HREDRAW | CS_VREDRAW; wc.cbClsExtra = 0; diff --git a/dlls/comctl32/tests/treeview.c b/dlls/comctl32/tests/treeview.c index 93010d3065e..c1ba7f309be 100644 --- a/dlls/comctl32/tests/treeview.c +++ b/dlls/comctl32/tests/treeview.c @@ -649,10 +649,23 @@ static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa START_TEST(treeview) { + HMODULE hComctl32; + BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*); WNDCLASSA wc; MSG msg; - InitCommonControls(); + hComctl32 = GetModuleHandleA("comctl32.dll"); + pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx"); + if (pInitCommonControlsEx) + { + INITCOMMONCONTROLSEX iccex; + iccex.dwSize = sizeof(iccex); + iccex.dwICC = ICC_TREEVIEW_CLASSES; + pInitCommonControlsEx(&iccex); + } + else + InitCommonControls(); + init_msg_sequences(MsgSequences, NUM_MSG_SEQUENCES); wc.style = CS_HREDRAW | CS_VREDRAW; diff --git a/dlls/comctl32/toolbar.c b/dlls/comctl32/toolbar.c index 6ab6f3fd45d..6d88461456e 100644 --- a/dlls/comctl32/toolbar.c +++ b/dlls/comctl32/toolbar.c @@ -283,11 +283,10 @@ TOOLBAR_DumpButton(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *bP, INT btn_ bP->fsState, bP->fsStyle, bP->dwData, bP->iString); TRACE("string %s\n", debugstr_w(TOOLBAR_GetText(infoPtr,bP))); if (internal) - TRACE("button %d id %d, hot=%s, row=%d, rect=(%d,%d)-(%d,%d)\n", + TRACE("button %d id %d, hot=%s, row=%d, rect=(%s)\n", btn_num, bP->idCommand, (bP->bHot) ? "TRUE":"FALSE", bP->nRow, - bP->rect.left, bP->rect.top, - bP->rect.right, bP->rect.bottom); + wine_dbgstr_rect(&bP->rect)); } } @@ -509,8 +508,7 @@ TOOLBAR_DrawDDFlatSeparator (const RECT *lpRect, HDC hdc, const TBUTTON_INFO *bt InflateRect (&myrect, -2, 0); - TRACE("rect=(%d,%d)-(%d,%d)\n", - myrect.left, myrect.top, myrect.right, myrect.bottom); + TRACE("rect=(%s)\n", wine_dbgstr_rect(&myrect)); newcolor = (infoPtr->clrBtnShadow == CLR_DEFAULT) ? comctl32_color.clrBtnShadow : infoPtr->clrBtnShadow; @@ -568,8 +566,8 @@ TOOLBAR_DrawString (const TOOLBAR_INFO *infoPtr, RECT *rcText, LPCWSTR lpText, /* draw text */ if (lpText) { - TRACE("string=%s rect=(%d,%d)-(%d,%d)\n", debugstr_w(lpText), - rcText->left, rcText->top, rcText->right, rcText->bottom); + TRACE("string=%s rect=(%s)\n", debugstr_w(lpText), + wine_dbgstr_rect(rcText)); hOldFont = SelectObject (hdc, infoPtr->hFont); if ((state & CDIS_HOT) && (dwItemCDFlag & TBCDRF_HILITEHOTTRACK )) { @@ -5321,8 +5319,7 @@ TOOLBAR_Unkwn463 (HWND hwnd, WPARAM wParam, LPARAM lParam) GetWindowRect(hwnd, &rc); MapWindowPoints(0, hwndParent, (LPPOINT)&rc, 2); - TRACE("mapped to (%d,%d)-(%d,%d)\n", - rc.left, rc.top, rc.right, rc.bottom); + TRACE("mapped to (%s)\n", wine_dbgstr_rect(&rc)); lpsize->cx = max(rc.right-rc.left, infoPtr->rcBound.right - infoPtr->rcBound.left); } @@ -6462,9 +6459,7 @@ TOOLBAR_Paint (HWND hwnd, WPARAM wParam) hdc = wParam==0 ? BeginPaint(hwnd, &ps) : (HDC)wParam; - TRACE("psrect=(%d,%d)-(%d,%d)\n", - ps.rcPaint.left, ps.rcPaint.top, - ps.rcPaint.right, ps.rcPaint.bottom); + TRACE("psrect=(%s)\n", wine_dbgstr_rect(&ps.rcPaint)); TOOLBAR_Refresh (hwnd, hdc, &ps); if (!wParam) EndPaint (hwnd, &ps); diff --git a/dlls/comctl32/trackbar.c b/dlls/comctl32/trackbar.c index bbb48c923fd..7cdfe71c606 100644 --- a/dlls/comctl32/trackbar.c +++ b/dlls/comctl32/trackbar.c @@ -439,8 +439,7 @@ TRACKBAR_CalcSelection (TRACKBAR_INFO *infoPtr) } } - TRACE("selection[left=%d, top=%d, right=%d, bottom=%d]\n", - selection->left, selection->top, selection->right, selection->bottom); + TRACE("selection[%s]\n", wine_dbgstr_rect(selection)); } static BOOL @@ -869,10 +868,7 @@ TRACKBAR_Refresh (TRACKBAR_INFO *infoPtr, HDC hdcDst) if (gcdrf == CDRF_DODEFAULT || notify_customdraw(infoPtr, &nmcd, CDDS_PREERASE) != CDRF_SKIPDEFAULT) { if ((theme = GetWindowTheme (infoPtr->hwndSelf))) { - DrawThemeBackground (theme, hdc, - (GetWindowLongW (infoPtr->hwndSelf, GWL_STYLE) & TBS_VERT) ? - TKP_TRACKVERT : TKP_TRACK, TKS_NORMAL, &rcClient, 0); - DrawThemeParentBackground (infoPtr->hwndSelf, hdc, &rcClient); + DrawThemeParentBackground (infoPtr->hwndSelf, hdc, 0); } else FillRect (hdc, &rcClient, GetSysColorBrush(COLOR_BTNFACE)); diff --git a/dlls/comctl32/treeview.c b/dlls/comctl32/treeview.c index 6a8e0c244ef..79f277c142f 100644 --- a/dlls/comctl32/treeview.c +++ b/dlls/comctl32/treeview.c @@ -2033,8 +2033,7 @@ TREEVIEW_GetItemRect(const TREEVIEW_INFO *infoPtr, BOOL fTextRect, LPRECT lpRect *lpRect = wineItem->rect; } - TRACE("%s [L:%d R:%d T:%d B:%d]\n", fTextRect ? "text" : "item", - lpRect->left, lpRect->right, lpRect->top, lpRect->bottom); + TRACE("%s [%s]\n", fTextRect ? "text" : "item", wine_dbgstr_rect(lpRect)); return TRUE; } @@ -2580,9 +2579,8 @@ TREEVIEW_DrawItem(const TREEVIEW_INFO *infoPtr, HDC hdc, TREEVIEW_ITEM *wineItem rcText.left = wineItem->textOffset; rcText.right = rcText.left + wineItem->textWidth + 4; - TRACE("drawing text %s at (%d,%d)-(%d,%d)\n", - debugstr_w(wineItem->pszText), - rcText.left, rcText.top, rcText.right, rcText.bottom); + TRACE("drawing text %s at (%s)\n", + debugstr_w(wineItem->pszText), wine_dbgstr_rect(&rcText)); /* Draw it */ ExtTextOutW(hdc, rcText.left + 2, rcText.top + 1, diff --git a/dlls/crypt32/decode.c b/dlls/crypt32/decode.c index be7e40fdd80..47b0ba6515e 100644 --- a/dlls/crypt32/decode.c +++ b/dlls/crypt32/decode.c @@ -30,6 +30,9 @@ * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject" */ +#include "config.h" +#include "wine/port.h" + #include #include #include diff --git a/dlls/crypt32/encode.c b/dlls/crypt32/encode.c index 6d5d152147e..f769afcd76a 100644 --- a/dlls/crypt32/encode.c +++ b/dlls/crypt32/encode.c @@ -30,6 +30,9 @@ * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject" */ +#include "config.h" +#include "wine/port.h" + #include #include #include diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index ff3b9216323..1c4d7bfa4e0 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -184,6 +184,7 @@ typedef struct IDirect3DDevice9Impl IDirect3DVertexDeclaration9 **convertedDecls; unsigned int numConvertedDecls, declArraySize; + BOOL notreset; } IDirect3DDevice9Impl; diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index ca4200f0ef7..27940b465f8 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -85,11 +85,16 @@ static ULONG WINAPI IDirect3DDevice9Impl_Release(LPDIRECT3DDEVICE9 iface) { static HRESULT WINAPI IDirect3DDevice9Impl_TestCooperativeLevel(LPDIRECT3DDEVICE9 iface) { IDirect3DDevice9Impl *This = (IDirect3DDevice9Impl *)iface; HRESULT hr; - TRACE("(%p) : Relay\n", This); + TRACE("(%p)\n", This); EnterCriticalSection(&d3d9_cs); hr = IWineD3DDevice_TestCooperativeLevel(This->WineD3DDevice); LeaveCriticalSection(&d3d9_cs); + if(hr == WINED3D_OK && This->notreset) { + TRACE("D3D9 Device is marked not reset\n"); + hr = D3DERR_DEVICENOTRESET; + } + return hr; } @@ -331,6 +336,7 @@ static HRESULT WINAPI IDirect3DDevice9Impl_Reset(LPDIRECT3DDEVICE9 iface, D3DP IWineD3DDevice_EnumResources(This->WineD3DDevice, reset_enum_callback, &resources_ok); if(!resources_ok) { WARN("The application is holding D3DPOOL_DEFAULT resources, rejecting reset\n"); + This->notreset = TRUE; return WINED3DERR_INVALIDCALL; } @@ -352,21 +358,26 @@ static HRESULT WINAPI IDirect3DDevice9Impl_Reset(LPDIRECT3DDEVICE9 iface, D3DP EnterCriticalSection(&d3d9_cs); hr = IWineD3DDevice_Reset(This->WineD3DDevice, &localParameters); LeaveCriticalSection(&d3d9_cs); - - pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; - pPresentationParameters->BackBufferHeight = localParameters.BackBufferHeight; - pPresentationParameters->BackBufferFormat = localParameters.BackBufferFormat; - pPresentationParameters->BackBufferCount = localParameters.BackBufferCount; - pPresentationParameters->MultiSampleType = localParameters.MultiSampleType; - pPresentationParameters->MultiSampleQuality = localParameters.MultiSampleQuality; - pPresentationParameters->SwapEffect = localParameters.SwapEffect; - pPresentationParameters->hDeviceWindow = localParameters.hDeviceWindow; - pPresentationParameters->Windowed = localParameters.Windowed; - pPresentationParameters->EnableAutoDepthStencil = localParameters.EnableAutoDepthStencil; - pPresentationParameters->AutoDepthStencilFormat = localParameters.AutoDepthStencilFormat; - pPresentationParameters->Flags = localParameters.Flags; - pPresentationParameters->FullScreen_RefreshRateInHz = localParameters.FullScreen_RefreshRateInHz; - pPresentationParameters->PresentationInterval = localParameters.PresentationInterval; + if(FAILED(hr)) { + This->notreset = TRUE; + + pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth; + pPresentationParameters->BackBufferHeight = localParameters.BackBufferHeight; + pPresentationParameters->BackBufferFormat = localParameters.BackBufferFormat; + pPresentationParameters->BackBufferCount = localParameters.BackBufferCount; + pPresentationParameters->MultiSampleType = localParameters.MultiSampleType; + pPresentationParameters->MultiSampleQuality = localParameters.MultiSampleQuality; + pPresentationParameters->SwapEffect = localParameters.SwapEffect; + pPresentationParameters->hDeviceWindow = localParameters.hDeviceWindow; + pPresentationParameters->Windowed = localParameters.Windowed; + pPresentationParameters->EnableAutoDepthStencil = localParameters.EnableAutoDepthStencil; + pPresentationParameters->AutoDepthStencilFormat = localParameters.AutoDepthStencilFormat; + pPresentationParameters->Flags = localParameters.Flags; + pPresentationParameters->FullScreen_RefreshRateInHz = localParameters.FullScreen_RefreshRateInHz; + pPresentationParameters->PresentationInterval = localParameters.PresentationInterval; + } else { + This->notreset = FALSE; + } return hr; } diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 8ad5d63bf55..0f1654de9d8 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -716,7 +716,7 @@ static void test_reset(void) IDirect3D9 *pD3d = NULL; IDirect3DDevice9 *pDevice = NULL; D3DPRESENT_PARAMETERS d3dpp; - D3DDISPLAYMODE d3ddm; + D3DDISPLAYMODE d3ddm, d3ddm2; D3DVIEWPORT9 vp; DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN); DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN); @@ -724,6 +724,8 @@ static void test_reset(void) IDirect3DSurface9 *surface; IDirect3DTexture9 *texture; IDirect3DVertexShader9 *shader; + BOOL support_800x600 = FALSE; + UINT i; pD3d = pDirect3DCreate9( D3D_SDK_VERSION ); ok(pD3d != NULL, "Failed to create IDirect3D9 object\n"); @@ -739,6 +741,27 @@ static void test_reset(void) d3dpp.BackBufferHeight = 600; d3dpp.BackBufferFormat = d3ddm.Format; + for(i = 0; i < IDirect3D9_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format); i++) { + ZeroMemory( &d3ddm2, sizeof(d3ddm2) ); + hr = IDirect3D9_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2); + ok(hr == D3D_OK, "IDirect3D9Impl_EnumAdapterModes returned %#x\n", hr); + + if(d3ddm2.Width == 800 && d3ddm2.Height == 600) { + support_800x600 = TRUE; + } + /* We use them as invalid modes */ + if((d3ddm2.Width == 801 && d3ddm2.Height == 600) || + (d3ddm2.Width == 32 && d3ddm2.Height == 32)) { + skip("This system supports a screen resolution of %dx%d, not running mode tests\n", + d3ddm2.Width, d3ddm2.Height); + goto cleanup; + } + } + if(!support_800x600) { + skip("Mode 800x600 not supported, skipping mode tests\n"); + goto cleanup; + } + hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice ); @@ -747,6 +770,8 @@ static void test_reset(void) skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr); goto cleanup; } + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr); width = GetSystemMetrics(SM_CXSCREEN); height = GetSystemMetrics(SM_CYSCREEN); @@ -779,6 +804,8 @@ static void test_reset(void) d3dpp.BackBufferFormat = d3ddm.Format; hr = IDirect3DDevice9_Reset(pDevice, &d3dpp); ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successfull reset returned %#x\n", hr); ZeroMemory(&vp, sizeof(vp)); hr = IDirect3DDevice9_GetViewport(pDevice, &vp); @@ -820,6 +847,8 @@ static void test_reset(void) d3dpp.BackBufferHeight = 300; hr = IDirect3DDevice9_Reset(pDevice, &d3dpp); ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successfull reset returned %#x\n", hr); width = GetSystemMetrics(SM_CXSCREEN); height = GetSystemMetrics(SM_CYSCREEN); @@ -865,26 +894,38 @@ static void test_reset(void) ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_Reset(pDevice, &d3dpp); ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr); IDirect3DSurface9_Release(surface); /* Reset again to get the device out of the lost state */ hr = IDirect3DDevice9_Reset(pDevice, &d3dpp); ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successfull reset returned %#x\n", hr); /* Scratch, sysmem and managed pools are fine */ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL); ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_Reset(pDevice, &d3dpp); ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successfull reset returned %#x\n", hr); IDirect3DSurface9_Release(surface); + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL); ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_Reset(pDevice, &d3dpp); ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successfull reset returned %#x\n", hr); IDirect3DSurface9_Release(surface); + hr = IDirect3DDevice9_CreateTexture(pDevice, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL); ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_Reset(pDevice, &d3dpp); ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successfull reset returned %#x\n", hr); IDirect3DTexture9_Release(texture); /* A reference held to an implicit surface causes failures as well */ @@ -892,9 +933,13 @@ static void test_reset(void) ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_Reset(pDevice, &d3dpp); ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr); IDirect3DSurface9_Release(surface); hr = IDirect3DDevice9_Reset(pDevice, &d3dpp); ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successfull reset returned %#x\n", hr); /* Shaders are fine as well */ hr = IDirect3DDevice9_CreateVertexShader(pDevice, simple_vs, &shader); @@ -903,6 +948,27 @@ static void test_reset(void) ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %s\n", DXGetErrorString9(hr)); IDirect3DVertexShader9_Release(shader); + /* Try setting invalid modes */ + ZeroMemory( &d3dpp, sizeof(d3dpp) ); + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.Windowed = FALSE; + d3dpp.BackBufferWidth = 32; + d3dpp.BackBufferHeight = 32; + hr = IDirect3DDevice9_Reset(pDevice, &d3dpp); + ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr); + + ZeroMemory( &d3dpp, sizeof(d3dpp) ); + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.Windowed = FALSE; + d3dpp.BackBufferWidth = 801; + d3dpp.BackBufferHeight = 600; + hr = IDirect3DDevice9_Reset(pDevice, &d3dpp); + ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_TestCooperativeLevel(pDevice); + ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr); + cleanup: if(pD3d) IDirect3D9_Release(pD3d); if(pDevice) IDirect3D9_Release(pDevice); @@ -1755,34 +1821,38 @@ static void test_set_stream_source(void) hr = IDirect3DDevice9_CreateVertexBuffer( device, 512, 0, 0, D3DPOOL_DEFAULT, &pVertexBuffer, NULL ); ok(hr == D3D_OK, "Failed to create a vertex buffer, hr = %s\n", DXGetErrorString9(hr)); if (SUCCEEDED(hr)) { - hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 32); - ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %s\n", - DXGetErrorString9(hr)); - hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 1, 32); - ok(hr == D3DERR_INVALIDCALL, "Unexpected result when setting the stream source, offset 1, hr = %s\n", - DXGetErrorString9(hr)); - hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 2, 32); - ok(hr == D3DERR_INVALIDCALL, "Unexpected result when setting the stream source, offset 2, hr = %s\n", - DXGetErrorString9(hr)); - hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 3, 32); - ok(hr == D3DERR_INVALIDCALL, "Unexpected result when setting the stream source, offset 3, hr = %s\n", - DXGetErrorString9(hr)); - hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 4, 32); - ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %s\n", - DXGetErrorString9(hr)); + /* Some cards(Geforce 7400 at least) accept non-aligned offsets, others(radeon 9000 verified) reject it, + * so accept both results. Wine currently rejects this to be able to optimize the vbo conversion, but writes + * a WARN + */ + hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 32); + ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %s\n", + DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 1, 32); + ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %s\n", + DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 2, 32); + ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %s\n", + DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 3, 32); + ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %s\n", + DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 4, 32); + ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %s\n", + DXGetErrorString9(hr)); } /* Try to set the NULL buffer with an offset and stride 0 */ hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0); ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0); - ok(hr == D3DERR_INVALIDCALL, "Unexpected result when setting the stream source, offset 1, hr = %s\n", + ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0); - ok(hr == D3DERR_INVALIDCALL, "Unexpected result when setting the stream source, offset 2, hr = %s\n", + ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0); - ok(hr == D3DERR_INVALIDCALL, "Unexpected result when setting the stream source, offset 3, hr = %s\n", + ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0); ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %s\n", @@ -1816,6 +1886,7 @@ START_TEST(device) test_mipmap_levels(); test_cursor(); test_reset(); + test_reset(); test_scene(); test_limits(); test_depthstenciltest(); diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index d20d3372f60..91c5c698698 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -119,7 +119,7 @@ static IDirect3DDevice9 *init_d3d9(void) present_parameters.EnableAutoDepthStencil = TRUE; present_parameters.AutoDepthStencilFormat = D3DFMT_D16; - hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr); + hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr); ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %s\n", DXGetErrorString9(hr)); return device_ptr; @@ -557,7 +557,7 @@ static void test_mova(IDirect3DDevice9 *device) IDirect3DVertexShader9 *mova_shader = NULL; IDirect3DVertexShader9 *mov_shader = NULL; HRESULT hr; - int i, j; + UINT i, j; hr = IDirect3DDevice9_CreateVertexShader(device, mova_test, &mova_shader); ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr); @@ -862,7 +862,8 @@ static void test_cube_wrap(IDirect3DDevice9 *device) IDirect3DSurface9 *surface = NULL; D3DLOCKED_RECT locked_rect; HRESULT hr; - INT x, y, face; + UINT x; + INT y, face; hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration); ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr); @@ -2364,7 +2365,9 @@ static void texture_transform_flags_test(IDirect3DDevice9 *device) hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float)); ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr); - /* What does this mean? Not sure... */ + /* D3DTFF_COUNT1 does not work on Nvidia drivers. It behaves like D3DTTFF_DISABLE. On ATI drivers + * it behaves like COUNT2 because normal textures require 2 coords + */ IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1); ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr); hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 5 * sizeof(float)); @@ -2397,9 +2400,11 @@ static void texture_transform_flags_test(IDirect3DDevice9 *device) color = getPixelColor(device, 160, 120); ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color); color = getPixelColor(device, 480, 120); - ok(color == 0x00ff8000 || color == 0x00fe7f00, "quad 3 has color %08x, expected 0x00ff8000\n", color); + ok(color == 0x00ff8000 || color == 0x00fe7f00 || color == 0x00000000, + "quad 3 has color %08x, expected 0x00ff8000\n", color); color = getPixelColor(device, 480, 360); - ok(color == 0x0033cc00 || color == 0x0032cb00, "quad 4 has color %08x, expected 0x0033cc00\n", color); + ok(color == 0x0033cc00 || color == 0x0032cb00 || color == 0x00FF0000 || color == 0x00FE0000, + "quad 4 has color %08x, expected 0x0033cc00\n", color); IDirect3DTexture9_Release(texture); @@ -2478,9 +2483,9 @@ static void texture_transform_flags_test(IDirect3DDevice9 *device) 1.0, 0.0, 0.1, 1.0, 1.0, 1.0 }; float mat[16] = {1.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 1.0}; + 0.0, 0.0, 1.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.0}; hr = IDirect3DDevice9_SetVertexDeclaration(device, decl); ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr)); @@ -2497,7 +2502,8 @@ static void texture_transform_flags_test(IDirect3DDevice9 *device) /* Now disable the w coordinate. Does that change the input, or the output. The coordinates * are swapped by the matrix. If it changes the input, the v coord will be missing(green), * otherwise the w will be missing(blue). - * turns out that the blue color is missing, so it is an output modification + * turns out that on nvidia cards the blue color is missing, so it is an output modification. + * On ATI cards the COUNT2 is ignored, and it behaves in the same way as COUNT3. */ IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr); @@ -2514,7 +2520,9 @@ static void texture_transform_flags_test(IDirect3DDevice9 *device) hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float)); ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr); - /* D3DTTFF_COUNT1. Set a NULL matrix, and count1, pass in all values as 1.0 */ + /* D3DTTFF_COUNT1. Set a NULL matrix, and count1, pass in all values as 1.0. Nvidia has count1 == + * disable. ATI extends it up to the amount of values needed for the volume texture + */ memset(mat, 0, sizeof(mat)); hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat); ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr)); @@ -2534,11 +2542,12 @@ static void texture_transform_flags_test(IDirect3DDevice9 *device) color = getPixelColor(device, 160, 360); ok(color == 0x00ffffff, "quad 1 has color %08x, expected 0x00ffffff\n", color); color = getPixelColor(device, 160, 120); - ok(color == 0x00ffff00, "quad 2 has color %08x, expected 0x00ffff00\n", color); + ok(color == 0x00ffff00 /* NV*/ || color == 0x00ffffff /* ATI */, + "quad 2 has color %08x, expected 0x00ffff00\n", color); color = getPixelColor(device, 480, 120); ok(color == 0x000000ff, "quad 3 has color %08x, expected 0x000000ff\n", color); color = getPixelColor(device, 480, 360); - ok(color == 0x00ffffff, "quad 4 has color %08x, expected 0x00ffffff\n", color); + ok(color == 0x00ffffff || color == 0x0000ff00, "quad 4 has color %08x, expected 0x00ffffff\n", color); hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff303030, 0.0, 0); ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr)); @@ -3070,7 +3079,8 @@ static void x8l8v8u8_test(IDirect3DDevice9 *device) hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr)); color = getPixelColor(device, 578, 430); - ok(color == 0x008262ca || color == 0x008363ca, "D3DFMT_X8L8V8U8 = 0x112131ca returns color %08x, expected 0x008262ca\n", color); + ok(color == 0x008262ca || color == 0x008363ca || color == 0x008362ca, + "D3DFMT_X8L8V8U8 = 0x112131ca returns color %08x, expected 0x008262ca\n", color); hr = IDirect3DDevice9_SetPixelShader(device, shader2); ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr); @@ -5449,6 +5459,7 @@ struct vertex_floatcolor { static void fixed_function_decl_test(IDirect3DDevice9 *device) { HRESULT hr; + BOOL s_ok, ub_ok, f_ok; DWORD color, size, i; void *data; static const D3DVERTEXELEMENT9 decl_elements_d3dcolor[] = { @@ -5588,6 +5599,7 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) hr = IDirect3DDevice9_BeginScene(device); ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr); + f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE; if(SUCCEEDED(hr)) { if(dcl_color) { hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color); @@ -5596,25 +5608,32 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr); } + /* Tests with non-standard fixed function types fail on the refrast. The ATI driver partially + * accepts them, the nvidia driver accepts them all. All those differences even though we're + * using software vertex processing. Doh! + */ if(dcl_ubyte) { hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte); ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr); hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0])); - ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr); + ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr); + ub_ok = SUCCEEDED(hr); } if(dcl_short) { hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_short); ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr); hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(quad3[0])); - ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr); + ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr); + s_ok = SUCCEEDED(hr); } if(dcl_float) { hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_float); ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr); hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(quad4[0])); - ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr); + ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr); + f_ok = SUCCEEDED(hr); } hr = IDirect3DDevice9_EndScene(device); @@ -5624,12 +5643,12 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); if(dcl_short) { color = getPixelColor(device, 480, 360); - ok(color == 0x000000ff, + ok(color == 0x000000ff || !s_ok, "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color); } if(dcl_ubyte) { color = getPixelColor(device, 160, 120); - ok(color == 0x0000ffff, + ok(color == 0x0000ffff || !ub_ok, "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color); } if(dcl_color) { @@ -5639,7 +5658,7 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) } if(dcl_float) { color = getPixelColor(device, 480, 120); - ok(color == 0x00ff0000, + ok(color == 0x00ff0000 || !f_ok, "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color); } @@ -5648,6 +5667,7 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) * with vertex buffers. It makes sure that the vertex buffer one works, while the above tests * whether the immediate mode code works */ + f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE; hr = IDirect3DDevice9_BeginScene(device); ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr); if(SUCCEEDED(hr)) { @@ -5676,7 +5696,9 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad2[0])); ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2); - ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, + "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + ub_ok = SUCCEEDED(hr); } if(dcl_short) { @@ -5690,7 +5712,9 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad3[0])); ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2); - ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, + "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + s_ok = SUCCEEDED(hr); } if(dcl_float) { @@ -5704,7 +5728,9 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad4[0])); ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2); - ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, + "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + f_ok = SUCCEEDED(hr); } hr = IDirect3DDevice9_EndScene(device); @@ -5719,12 +5745,12 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); if(dcl_short) { color = getPixelColor(device, 480, 360); - ok(color == 0x000000ff, + ok(color == 0x000000ff || !s_ok, "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color); } if(dcl_ubyte) { color = getPixelColor(device, 160, 120); - ok(color == 0x0000ffff, + ok(color == 0x0000ffff || !ub_ok, "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color); } if(dcl_color) { @@ -5734,7 +5760,7 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) } if(dcl_float) { color = getPixelColor(device, 480, 120); - ok(color == 0x00ff0000, + ok(color == 0x00ff0000 || !f_ok, "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color); } @@ -5847,11 +5873,14 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) hr = IDirect3DDevice9_BeginScene(device); ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr)); + ub_ok = FALSE; if(SUCCEEDED(hr)) { hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2); ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2); - ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, + "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + ub_ok = SUCCEEDED(hr); hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color_2); ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr)); @@ -5861,7 +5890,9 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2); ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr)); hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 8, 2); - ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, + "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr); + ok(ub_ok == SUCCEEDED(hr), "dcl_ubyte_2 returned two different results\n"); hr = IDirect3DDevice9_EndScene(device); ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr)); @@ -5871,16 +5902,16 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) if(i == 0) { color = getPixelColor(device, 480, 360); ok(color == 0x00ff0000, - "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x00ff0000\n", color); + "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ff0000\n", color); color = getPixelColor(device, 160, 120); ok(color == 0x00ffffff, - "Unused quad returned color %08x, expected 0x00ffffff\n", color); + "Unused quad returned color %08x, expected 0x00ffffff\n", color); color = getPixelColor(device, 160, 360); - ok(color == 0x000000ff, - "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x000000ff\n", color); + ok(color == 0x000000ff || !ub_ok, + "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color); color = getPixelColor(device, 480, 120); - ok(color == 0x000000ff, - "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x000000ff\n", color); + ok(color == 0x000000ff || !ub_ok, + "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color); } else { color = getPixelColor(device, 480, 360); ok(color == 0x000000ff, @@ -5889,10 +5920,10 @@ static void fixed_function_decl_test(IDirect3DDevice9 *device) ok(color == 0x00ffffff, "Unused quad returned color %08x, expected 0x00ffffff\n", color); color = getPixelColor(device, 160, 360); - ok(color == 0x00ff0000, + ok(color == 0x00ff0000 || !ub_ok, "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color); color = getPixelColor(device, 480, 120); - ok(color == 0x00ff0000, + ok(color == 0x00ff0000 || !ub_ok, "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color); } } @@ -6056,6 +6087,124 @@ static void test_vshader_float16(IDirect3DDevice9 *device) IDirect3DVertexBuffer9_Release(buffer); } +static void conditional_np2_repeat_test(IDirect3DDevice9 *device) +{ + D3DCAPS9 caps; + IDirect3DTexture9 *texture; + HRESULT hr; + D3DLOCKED_RECT rect; + unsigned int x, y; + DWORD *dst, color; + const float quad[] = { + -1.0, -1.0, 0.1, -0.2, -0.2, + 1.0, -1.0, 0.1, 1.2, -0.2, + -1.0, 1.0, 0.1, -0.2, 1.2, + 1.0, 1.0, 0.1, 1.2, 1.2 + }; + memset(&caps, 0, sizeof(caps)); + + hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); + ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%s\n", DXGetErrorString9(hr)); + if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) { + /* NP2 conditional requires the POW2 flag. Check that while we're at it */ + ok((caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) == 0, + "Card has conditional NP2 support without power of two restriction set\n"); + skip("Card has unconditional pow2 support, skipping conditional NP2 tests\n"); + return; + } else if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) { + skip("No conditional NP2 support, skipping conditional NP2 tests\n"); + return; + } + + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0); + ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_CreateTexture(device, 10, 10, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%s\n", DXGetErrorString9(hr)); + + memset(&rect, 0, sizeof(rect)); + hr = IDirect3DTexture9_LockRect(texture, 0, &rect, NULL, 0); + ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed hr=%s\n", DXGetErrorString9(hr)); + for(y = 0; y < 10; y++) { + for(x = 0; x < 10; x++) { + dst = (DWORD *) ((BYTE *) rect.pBits + y * rect.Pitch + x * sizeof(DWORD)); + if(x == 0 || x == 9 || y == 0 || y == 9) { + *dst = 0x00ff0000; + } else { + *dst = 0x000000ff; + } + } + } + hr = IDirect3DTexture9_UnlockRect(texture, 0); + ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed hr=%s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture); + ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); + ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); + ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1); + ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_BeginScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%s\n", DXGetErrorString9(hr)); + if(SUCCEEDED(hr)) { + hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5); + ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr)); + + hr = IDirect3DDevice9_EndScene(device); + ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%s\n", DXGetErrorString9(hr)); + } + + IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + + color = getPixelColor(device, 1, 1); + ok(color == 0x00ff0000, "NP2: Pixel 1, 1 has color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 639, 479); + ok(color == 0x00ff0000, "NP2: Pixel 639, 479 has color %08x, expected 0x00ff0000\n", color); + + color = getPixelColor(device, 135, 101); + ok(color == 0x00ff0000, "NP2: Pixel 135, 101 has color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 140, 101); + ok(color == 0x00ff0000, "NP2: Pixel 140, 101 has color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 135, 105); + ok(color == 0x00ff0000, "NP2: Pixel 135, 105 has color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 140, 105); + ok(color == 0x000000ff, "NP2: Pixel 140, 105 has color %08x, expected 0x000000ff\n", color); + + color = getPixelColor(device, 135, 376); + ok(color == 0x00ff0000, "NP2: Pixel 135, 376 has color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 140, 376); + ok(color == 0x000000ff, "NP2: Pixel 140, 376 has color %08x, expected 0x000000ff\n", color); + color = getPixelColor(device, 135, 379); + ok(color == 0x00ff0000, "NP2: Pixel 135, 379 has color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 140, 379); + ok(color == 0x00ff0000, "NP2: Pixel 140, 379 has color %08x, expected 0x00ff0000\n", color); + + color = getPixelColor(device, 500, 101); + ok(color == 0x00ff0000, "NP2: Pixel 500, 101 has color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 504, 101); + ok(color == 0x00ff0000, "NP2: Pixel 504, 101 has color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 500, 105); + ok(color == 0x000000ff, "NP2: Pixel 500, 105 has color %08x, expected 0x000000ff\n", color); + color = getPixelColor(device, 504, 105); + ok(color == 0x00ff0000, "NP2: Pixel 504, 105 has color %08x, expected 0x00ff0000\n", color); + + color = getPixelColor(device, 500, 376); + ok(color == 0x000000ff, "NP2: Pixel 500, 376 has color %08x, expected 0x000000ff\n", color); + color = getPixelColor(device, 504, 376); + ok(color == 0x00ff0000, "NP2: Pixel 504, 376 has color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 500, 380); + ok(color == 0x00ff0000, "NP2: Pixel 500, 380 has color %08x, expected 0x00ff0000\n", color); + color = getPixelColor(device, 504, 380); + ok(color == 0x00ff0000, "NP2: Pixel 504, 380 has color %08x, expected 0x00ff0000\n", color); + + hr = IDirect3DDevice9_SetTexture(device, 0, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%s\n", DXGetErrorString9(hr)); + IDirect3DTexture9_Release(texture); +} + START_TEST(visual) { IDirect3DDevice9 *device_ptr; @@ -6137,6 +6286,7 @@ START_TEST(visual) texture_transform_flags_test(device_ptr); autogen_mipmap_test(device_ptr); fixed_function_decl_test(device_ptr); + conditional_np2_repeat_test(device_ptr); if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1)) { diff --git a/dlls/d3dx8/d3dx8_main.c b/dlls/d3dx8/d3dx8_main.c index c24aedc74a3..ee897a8e47c 100644 --- a/dlls/d3dx8/d3dx8_main.c +++ b/dlls/d3dx8/d3dx8_main.c @@ -73,7 +73,7 @@ HRESULT WINAPI D3DXAssembleShader(LPCVOID pSrcData, UINT SrcDataLen, DWORD Flags return D3D_OK; } -HRESULT WINAPI D3DXAssembleShaderFromFileA(LPSTR pSrcFile, DWORD Flags, +HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR pSrcFile, DWORD Flags, LPD3DXBUFFER* ppConstants, LPD3DXBUFFER* ppCompiledShader, LPD3DXBUFFER* ppCompilationErrors) { @@ -91,7 +91,7 @@ HRESULT WINAPI D3DXAssembleShaderFromFileA(LPSTR pSrcFile, DWORD Flags, return ret; } -HRESULT WINAPI D3DXAssembleShaderFromFileW(LPWSTR pSrcFile, DWORD Flags, +HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR pSrcFile, DWORD Flags, LPD3DXBUFFER* ppConstants, LPD3DXBUFFER* ppCompiledShader, LPD3DXBUFFER* ppCompilationErrors) { diff --git a/dlls/d3dx8/math.c b/dlls/d3dx8/math.c index 0446198062f..6573c684a34 100644 --- a/dlls/d3dx8/math.c +++ b/dlls/d3dx8/math.c @@ -59,7 +59,7 @@ D3DXCOLOR* WINAPI D3DXColorAdjustSaturation(D3DXCOLOR *pout, CONST D3DXCOLOR *pc /*_________________D3DXMatrix____________________*/ -D3DXMATRIX* WINAPI D3DXMatrixAffineTransformation(D3DXMATRIX *pout, float scaling, D3DXVECTOR3 *rotationcenter, D3DXQUATERNION *rotation, D3DXVECTOR3 *translation) +D3DXMATRIX* WINAPI D3DXMatrixAffineTransformation(D3DXMATRIX *pout, FLOAT scaling, CONST D3DXVECTOR3 *rotationcenter, CONST D3DXQUATERNION *rotation, CONST D3DXVECTOR3 *translation) { D3DXMATRIX m1, m2, m3, m4, m5, p1, p2, p3; diff --git a/dlls/dbghelp/Makefile.in b/dlls/dbghelp/Makefile.in index 280e199c9ac..fa94a1fe1c8 100644 --- a/dlls/dbghelp/Makefile.in +++ b/dlls/dbghelp/Makefile.in @@ -5,6 +5,7 @@ VPATH = @srcdir@ MODULE = dbghelp.dll IMPORTLIB = libdbghelp.$(IMPLIBEXT) IMPORTS = psapi kernel32 ntdll +DELAYIMPORTS = version C_SRCS = \ coff.c \ diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 99b8b542f9d..c81f778331d 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -206,12 +206,12 @@ struct symt_function struct vector vchildren; /* locals, params, blocks, start/end, labels */ }; -struct symt_function_point +struct symt_hierarchy_point { struct symt symt; /* either SymTagFunctionDebugStart, SymTagFunctionDebugEnd, SymTagLabel */ - struct symt_function* parent; + struct hash_table_elt hash_elt; /* if label (and in compiland's hash table if global) */ + struct symt* parent; /* symt_function or symt_compiland */ struct location loc; - const char* name; /* for labels */ }; struct symt_public @@ -256,6 +256,7 @@ struct symt_basic struct symt_enum { struct symt symt; + struct symt* base_type; const char* name; struct vector vchildren; }; @@ -548,7 +549,7 @@ extern struct symt_block* symt_close_func_block(struct module* module, struct symt_function* func, struct symt_block* block, unsigned pc); -extern struct symt_function_point* +extern struct symt_hierarchy_point* symt_add_function_point(struct module* module, struct symt_function* func, enum SymTagEnum point, @@ -568,6 +569,10 @@ extern struct symt_data* struct symt_compiland* parent, const char* name, struct symt* type, const VARIANT* v); +extern struct symt_hierarchy_point* + symt_new_label(struct module* module, + struct symt_compiland* compiland, + const char* name, unsigned long address); /* type.c */ extern void symt_init_basic(struct module* module); @@ -587,7 +592,8 @@ extern BOOL symt_add_udt_element(struct module* module, struct symt* elt_type, unsigned offset, unsigned size); extern struct symt_enum* - symt_new_enum(struct module* module, const char* typename); + symt_new_enum(struct module* module, const char* typename, + struct symt* basetype); extern BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type, const char* name, int value); diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 133af6677a6..aee3dea39c0 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -167,6 +167,13 @@ typedef struct dwarf2_traverse_context_s unsigned char word_size; } dwarf2_traverse_context_t; +/* symt_cache indexes */ +#define sc_void 0 +#define sc_int1 1 +#define sc_int2 2 +#define sc_int4 3 +#define sc_num 4 + typedef struct dwarf2_parse_context_s { const dwarf2_section_t* sections; @@ -179,6 +186,7 @@ typedef struct dwarf2_parse_context_s unsigned long load_offset; unsigned long ref_offset; unsigned char word_size; + struct symt* symt_cache[sc_num]; /* void, int1, int2, int4 */ } dwarf2_parse_context_t; /* stored in the dbghelp's module internal structure for later reuse */ @@ -932,7 +940,7 @@ static struct symt* dwarf2_parse_base_type(dwarf2_parse_context_t* ctx, struct attribute size; struct attribute encoding; enum BasicType bt; - + int cache_idx = -1; if (di->symt) return di->symt; TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); @@ -956,6 +964,25 @@ static struct symt* dwarf2_parse_base_type(dwarf2_parse_context_t* ctx, default: bt = btNoType; break; } di->symt = &symt_new_basic(ctx->module, bt, name.u.string, size.u.uvalue)->symt; + switch (bt) + { + case btVoid: + assert(size.u.uvalue == 0); + cache_idx = sc_void; + break; + case btInt: + switch (size.u.uvalue) + { + case 1: cache_idx = sc_int1; break; + case 2: cache_idx = sc_int2; break; + case 4: cache_idx = sc_int4; break; + } + break; + default: break; + } + if (!ctx->symt_cache[cache_idx]) + ctx->symt_cache[cache_idx] = di->symt; + if (di->abbrev->have_child) FIXME("Unsupported children\n"); return di->symt; } @@ -991,8 +1018,10 @@ static struct symt* dwarf2_parse_pointer_type(dwarf2_parse_context_t* ctx, if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = 0; if (!(ref_type = dwarf2_lookup_type(ctx, di))) - ref_type = &symt_new_basic(ctx->module, btVoid, "void", 0)->symt; - + { + ref_type = ctx->symt_cache[sc_void]; + assert(ref_type); + } di->symt = &symt_new_pointer(ctx->module, ref_type)->symt; if (di->abbrev->have_child) FIXME("Unsupported children\n"); return di->symt; @@ -1216,15 +1245,24 @@ static struct symt* dwarf2_parse_enumeration_type(dwarf2_parse_context_t* ctx, { struct attribute name; struct attribute size; + struct symt_basic* basetype; if (di->symt) return di->symt; TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); if (!dwarf2_find_attribute(ctx, di, DW_AT_name, &name)) name.u.string = NULL; - if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = 0; + if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &size)) size.u.uvalue = 4; + + switch (size.u.uvalue) /* FIXME: that's wrong */ + { + case 1: basetype = symt_new_basic(ctx->module, btInt, "char", 1); break; + case 2: basetype = symt_new_basic(ctx->module, btInt, "short", 2); break; + default: + case 4: basetype = symt_new_basic(ctx->module, btInt, "int", 4); break; + } - di->symt = &symt_new_enum(ctx->module, name.u.string)->symt; + di->symt = &symt_new_enum(ctx->module, name.u.string, &basetype->symt)->symt; if (di->abbrev->have_child) /* any interest to not have child ? */ { @@ -1555,7 +1593,10 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx, is_decl.u.uvalue = 0; if (!(ret_type = dwarf2_lookup_type(ctx, di))) - ret_type = &symt_new_basic(ctx->module, btVoid, "void", 0)->symt; + { + ret_type = ctx->symt_cache[sc_void]; + assert(ret_type); + } /* FIXME: assuming C source code */ sig_type = symt_new_function_signature(ctx->module, ret_type, CV_CALL_FAR_C); @@ -1648,7 +1689,10 @@ static struct symt* dwarf2_parse_subroutine_type(dwarf2_parse_context_t* ctx, TRACE("%s, for %s\n", dwarf2_debug_ctx(ctx), dwarf2_debug_di(di)); if (!(ret_type = dwarf2_lookup_type(ctx, di))) - ret_type = &symt_new_basic(ctx->module, btVoid, "void", 0)->symt; + { + ret_type = ctx->symt_cache[sc_void]; + assert(ret_type); + } /* FIXME: assuming C source code */ sig_type = symt_new_function_signature(ctx->module, ret_type, CV_CALL_FAR_C); @@ -1970,6 +2014,8 @@ static BOOL dwarf2_parse_compilation_unit(const dwarf2_section_t* sections, ctx.thunks = thunks; ctx.load_offset = load_offset; ctx.ref_offset = comp_unit_cursor - sections[section_debug].address; + memset(ctx.symt_cache, 0, sizeof(ctx.symt_cache)); + ctx.symt_cache[sc_void] = &symt_new_basic(module, btVoid, "void", 0)->symt; traverse.start_data = comp_unit_cursor + sizeof(dwarf2_comp_unit_stream_t); traverse.data = traverse.start_data; @@ -2070,7 +2116,7 @@ static enum location_error loc_compute_frame(struct process* pcs, psym = vector_at(&func->vchildren, i); if ((*psym)->tag == SymTagCustom) { - pframe = &((struct symt_function_point*)*psym)->loc; + pframe = &((struct symt_hierarchy_point*)*psym)->loc; /* First, recompute the frame information, if needed */ switch (pframe->kind) diff --git a/dlls/dbghelp/minidump.c b/dlls/dbghelp/minidump.c index 9ae530745ce..4eec39f6f03 100644 --- a/dlls/dbghelp/minidump.c +++ b/dlls/dbghelp/minidump.c @@ -222,6 +222,7 @@ static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx, else if (tid == GetCurrentThreadId() && except) { CONTEXT lctx, *pctx; + mdThd->SuspendCount = 1; if (except->ClientPointers) { EXCEPTION_POINTERS ep; @@ -237,6 +238,7 @@ static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx, memcpy(ctx, pctx, sizeof(*ctx)); fetch_thread_stack(dc, tbi.TebBaseAddress, pctx, &mdThd->Stack); } + else mdThd->SuspendCount = 0; } } CloseHandle(hThread); @@ -327,6 +329,28 @@ static void fetch_modules_info(struct dump_context* dc) elf_enum_modules(dc->hProcess, fetch_elf_module_info_cb, dc); } +static void fetch_module_versioninfo(LPCWSTR filename, VS_FIXEDFILEINFO* ffi) +{ + DWORD handle; + DWORD sz; + static const WCHAR backslashW[] = {'\\', '\0'}; + + memset(ffi, 0, sizeof(*ffi)); + if ((sz = GetFileVersionInfoSizeW(filename, &handle))) + { + void* info = HeapAlloc(GetProcessHeap(), 0, sz); + if (info && GetFileVersionInfoW(filename, handle, sz, info)) + { + VS_FIXEDFILEINFO* ptr; + UINT len; + + if (VerQueryValueW(info, backslashW, (void*)&ptr, &len)) + memcpy(ffi, ptr, min(len, sizeof(*ffi))); + } + HeapFree(GetProcessHeap(), 0, info); + } +} + /****************************************************************** * add_memory_block * @@ -381,9 +405,8 @@ static void append(struct dump_context* dc, void* data, unsigned size) * * Write in File the exception information from pcs */ -static void dump_exception_info(struct dump_context* dc, - const MINIDUMP_EXCEPTION_INFORMATION* except, - DWORD *size) +static unsigned dump_exception_info(struct dump_context* dc, + const MINIDUMP_EXCEPTION_INFORMATION* except) { MINIDUMP_EXCEPTION_STREAM mdExcpt; EXCEPTION_RECORD rec, *prec; @@ -422,8 +445,8 @@ static void dump_exception_info(struct dump_context* dc, mdExcpt.ThreadContext.Rva = dc->rva + sizeof(mdExcpt); append(dc, &mdExcpt, sizeof(mdExcpt)); - *size = sizeof(mdExcpt); append(dc, pctx, sizeof(*pctx)); + return sizeof(mdExcpt); } /****************************************************************** @@ -431,7 +454,7 @@ static void dump_exception_info(struct dump_context* dc, * * Write in File the modules from pcs */ -static void dump_modules(struct dump_context* dc, BOOL dump_elf, DWORD *size) +static unsigned dump_modules(struct dump_context* dc, BOOL dump_elf) { MINIDUMP_MODULE mdModule; MINIDUMP_MODULE_LIST mdModuleList; @@ -440,6 +463,7 @@ static void dump_modules(struct dump_context* dc, BOOL dump_elf, DWORD *size ULONG i, nmod; RVA rva_base; DWORD flags_out; + unsigned sz; for (i = nmod = 0; i < dc->num_modules; i++) { @@ -460,7 +484,7 @@ static void dump_modules(struct dump_context* dc, BOOL dump_elf, DWORD *size in the minidump file. Since each string is referenced by RVA they can all safely be located anywhere between streams in the file, so the end of this stream is sufficient. */ rva_base = dc->rva; - dc->rva += *size = sizeof(mdModuleList.NumberOfModules) + sizeof(mdModule) * nmod; + dc->rva += sz = sizeof(mdModuleList.NumberOfModules) + sizeof(mdModule) * nmod; for (i = 0; i < dc->num_modules; i++) { if ((dc->modules[i].is_elf && !dump_elf) || @@ -513,7 +537,7 @@ static void dump_modules(struct dump_context* dc, BOOL dump_elf, DWORD *size mdModule.ModuleNameRva = dc->rva; ms->Length -= sizeof(WCHAR); append(dc, ms, sizeof(ULONG) + ms->Length + sizeof(WCHAR)); - memset(&mdModule.VersionInfo, 0, sizeof(mdModule.VersionInfo)); /* FIXME */ + fetch_module_versioninfo(ms->Buffer, &mdModule.VersionInfo); mdModule.CvRecord.DataSize = 0; /* FIXME */ mdModule.CvRecord.Rva = 0; /* FIXME */ mdModule.MiscRecord.DataSize = 0; /* FIXME */ @@ -528,6 +552,8 @@ static void dump_modules(struct dump_context* dc, BOOL dump_elf, DWORD *size } writeat(dc, rva_base, &mdModuleList.NumberOfModules, sizeof(mdModuleList.NumberOfModules)); + + return sz; } /****************************************************************** @@ -535,7 +561,7 @@ static void dump_modules(struct dump_context* dc, BOOL dump_elf, DWORD *size * * Dumps into File the information about the system */ -static void dump_system_info(struct dump_context* dc, DWORD *size) +static unsigned dump_system_info(struct dump_context* dc) { MINIDUMP_SYSTEM_INFO mdSysInfo; SYSTEM_INFO sysInfo; @@ -565,7 +591,6 @@ static void dump_system_info(struct dump_context* dc, DWORD *size) memset(&mdSysInfo.Cpu, 0, sizeof(mdSysInfo.Cpu)); append(dc, &mdSysInfo, sizeof(mdSysInfo)); - *size = sizeof(mdSysInfo); /* write the service pack version string after this stream. It is referenced within the stream by its RVA in the file. */ @@ -573,6 +598,8 @@ static void dump_system_info(struct dump_context* dc, DWORD *size) WriteFile(dc->hFile, &slen, sizeof(slen), &written, NULL); WriteFile(dc->hFile, osInfo.szCSDVersion, slen, &written, NULL); dc->rva += sizeof(ULONG) + slen; + + return sizeof(mdSysInfo); } /****************************************************************** @@ -580,9 +607,8 @@ static void dump_system_info(struct dump_context* dc, DWORD *size) * * Dumps into File the information about running threads */ -static void dump_threads(struct dump_context* dc, - const MINIDUMP_EXCEPTION_INFORMATION* except, - DWORD *size) +static unsigned dump_threads(struct dump_context* dc, + const MINIDUMP_EXCEPTION_INFORMATION* except) { MINIDUMP_THREAD mdThd; MINIDUMP_THREAD_LIST mdThdList; @@ -662,7 +688,8 @@ static void dump_threads(struct dump_context* dc, } writeat(dc, rva_base, &mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads)); - *size = dc->rva - rva_base; + + return dc->rva - rva_base; } /****************************************************************** @@ -670,12 +697,12 @@ static void dump_threads(struct dump_context* dc, * * dumps information about the memory of the process (stack of the threads) */ -static void dump_memory_info(struct dump_context* dc, DWORD* size) +static unsigned dump_memory_info(struct dump_context* dc) { MINIDUMP_MEMORY_LIST mdMemList; MINIDUMP_MEMORY_DESCRIPTOR mdMem; DWORD written; - unsigned i, pos, len; + unsigned i, pos, len, sz; RVA rva_base; char tmp[1024]; @@ -683,9 +710,9 @@ static void dump_memory_info(struct dump_context* dc, DWORD* size) append(dc, &mdMemList.NumberOfMemoryRanges, sizeof(mdMemList.NumberOfMemoryRanges)); rva_base = dc->rva; - dc->rva += mdMemList.NumberOfMemoryRanges * sizeof(mdMem); - *size = sizeof(mdMemList.NumberOfMemoryRanges) + - mdMemList.NumberOfMemoryRanges * sizeof(mdMem); + sz = mdMemList.NumberOfMemoryRanges * sizeof(mdMem); + dc->rva += sz; + sz += sizeof(mdMemList.NumberOfMemoryRanges); for (i = 0; i < dc->num_mem; i++) { @@ -708,9 +735,11 @@ static void dump_memory_info(struct dump_context* dc, DWORD* size) writeat(dc, dc->mem[i].rva, &mdMem.Memory.Rva, sizeof(mdMem.Memory.Rva)); } } + + return sz; } -static void dump_misc_info(struct dump_context* dc, DWORD* size) +static unsigned dump_misc_info(struct dump_context* dc) { MINIDUMP_MISC_INFO mmi; @@ -723,7 +752,7 @@ static void dump_misc_info(struct dump_context* dc, DWORD* size) mmi.ProcessUserTime = 0; append(dc, &mmi, sizeof(mmi)); - *size = sizeof(mmi); + return sizeof(mmi); } /****************************************************************** @@ -782,7 +811,6 @@ BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, HANDLE hFile, mdHead.StreamDirectoryRva = sizeof(mdHead); mdHead.u.TimeDateStamp = time(NULL); mdHead.Flags = DumpType; - mdHead.CheckSum = 0; append(&dc, &mdHead, sizeof(mdHead)); /* 3) write stream directories */ @@ -794,37 +822,37 @@ BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, HANDLE hFile, /* must be first in minidump */ mdDir.StreamType = SystemInfoStream; mdDir.Location.Rva = dc.rva; - dump_system_info(&dc, &mdDir.Location.DataSize); + mdDir.Location.DataSize = dump_system_info(&dc); writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), &mdDir, sizeof(mdDir)); mdDir.StreamType = ThreadListStream; mdDir.Location.Rva = dc.rva; - dump_threads(&dc, ExceptionParam, &mdDir.Location.DataSize); + mdDir.Location.DataSize = dump_threads(&dc, ExceptionParam); writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), &mdDir, sizeof(mdDir)); mdDir.StreamType = ModuleListStream; mdDir.Location.Rva = dc.rva; - dump_modules(&dc, FALSE, &mdDir.Location.DataSize); + mdDir.Location.DataSize = dump_modules(&dc, FALSE); writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), &mdDir, sizeof(mdDir)); mdDir.StreamType = 0xfff0; /* FIXME: this is part of MS reserved streams */ mdDir.Location.Rva = dc.rva; - dump_modules(&dc, TRUE, &mdDir.Location.DataSize); + mdDir.Location.DataSize = dump_modules(&dc, TRUE); writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), &mdDir, sizeof(mdDir)); mdDir.StreamType = MemoryListStream; mdDir.Location.Rva = dc.rva; - dump_memory_info(&dc, &mdDir.Location.DataSize); + mdDir.Location.DataSize = dump_memory_info(&dc); writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), &mdDir, sizeof(mdDir)); mdDir.StreamType = MiscInfoStream; mdDir.Location.Rva = dc.rva; - dump_misc_info(&dc, &mdDir.Location.DataSize); + mdDir.Location.DataSize = dump_misc_info(&dc); writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), &mdDir, sizeof(mdDir)); @@ -833,7 +861,7 @@ BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, HANDLE hFile, { mdDir.StreamType = ExceptionStream; mdDir.Location.Rva = dc.rva; - dump_exception_info(&dc, ExceptionParam, &mdDir.Location.DataSize); + mdDir.Location.DataSize = dump_exception_info(&dc, ExceptionParam); writeat(&dc, mdHead.StreamDirectoryRva + idx_stream++ * sizeof(mdDir), &mdDir, sizeof(mdDir)); } diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index 5e6f8a84bcf..af09f1fd072 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -125,12 +125,21 @@ static void codeview_init_basic_types(struct module* module) cv_basic_types[T_USHORT] = &symt_new_basic(module, btUInt, "unsigned short", 2)->symt; cv_basic_types[T_ULONG] = &symt_new_basic(module, btUInt, "unsigned long", 4)->symt; cv_basic_types[T_UQUAD] = &symt_new_basic(module, btUInt, "unsigned long long", 8)->symt; + cv_basic_types[T_BOOL08] = &symt_new_basic(module, btBool, "BOOL08", 1)->symt; + cv_basic_types[T_BOOL16] = &symt_new_basic(module, btBool, "BOOL16", 2)->symt; + cv_basic_types[T_BOOL32] = &symt_new_basic(module, btBool, "BOOL32", 4)->symt; + cv_basic_types[T_BOOL64] = &symt_new_basic(module, btBool, "BOOL64", 8)->symt; cv_basic_types[T_REAL32] = &symt_new_basic(module, btFloat, "float", 4)->symt; cv_basic_types[T_REAL64] = &symt_new_basic(module, btFloat, "double", 8)->symt; cv_basic_types[T_RCHAR] = &symt_new_basic(module, btInt, "signed char", 1)->symt; cv_basic_types[T_WCHAR] = &symt_new_basic(module, btWChar, "wchar_t", 2)->symt; + cv_basic_types[T_INT2] = &symt_new_basic(module, btInt, "INT2", 2)->symt; + cv_basic_types[T_UINT2] = &symt_new_basic(module, btUInt, "UINT2", 2)->symt; cv_basic_types[T_INT4] = &symt_new_basic(module, btInt, "INT4", 4)->symt; cv_basic_types[T_UINT4] = &symt_new_basic(module, btUInt, "UINT4", 4)->symt; + cv_basic_types[T_INT8] = &symt_new_basic(module, btInt, "INT8", 8)->symt; + cv_basic_types[T_UINT8] = &symt_new_basic(module, btUInt, "UINT8", 8)->symt; + cv_basic_types[T_HRESULT]= &symt_new_basic(module, btUInt, "HRESULT", 4)->symt; cv_basic_types[T_32PVOID] = &symt_new_pointer(module, cv_basic_types[T_VOID])->symt; cv_basic_types[T_32PCHAR] = &symt_new_pointer(module, cv_basic_types[T_CHAR])->symt; @@ -141,12 +150,21 @@ static void codeview_init_basic_types(struct module* module) cv_basic_types[T_32PUSHORT] = &symt_new_pointer(module, cv_basic_types[T_USHORT])->symt; cv_basic_types[T_32PULONG] = &symt_new_pointer(module, cv_basic_types[T_ULONG])->symt; cv_basic_types[T_32PUQUAD] = &symt_new_pointer(module, cv_basic_types[T_UQUAD])->symt; + cv_basic_types[T_32PBOOL08] = &symt_new_pointer(module, cv_basic_types[T_BOOL08])->symt; + cv_basic_types[T_32PBOOL16] = &symt_new_pointer(module, cv_basic_types[T_BOOL16])->symt; + cv_basic_types[T_32PBOOL32] = &symt_new_pointer(module, cv_basic_types[T_BOOL32])->symt; + cv_basic_types[T_32PBOOL64] = &symt_new_pointer(module, cv_basic_types[T_BOOL64])->symt; cv_basic_types[T_32PREAL32] = &symt_new_pointer(module, cv_basic_types[T_REAL32])->symt; cv_basic_types[T_32PREAL64] = &symt_new_pointer(module, cv_basic_types[T_REAL64])->symt; cv_basic_types[T_32PRCHAR] = &symt_new_pointer(module, cv_basic_types[T_RCHAR])->symt; cv_basic_types[T_32PWCHAR] = &symt_new_pointer(module, cv_basic_types[T_WCHAR])->symt; + cv_basic_types[T_32PINT2] = &symt_new_pointer(module, cv_basic_types[T_INT2])->symt; + cv_basic_types[T_32PUINT2] = &symt_new_pointer(module, cv_basic_types[T_UINT2])->symt; cv_basic_types[T_32PINT4] = &symt_new_pointer(module, cv_basic_types[T_INT4])->symt; cv_basic_types[T_32PUINT4] = &symt_new_pointer(module, cv_basic_types[T_UINT4])->symt; + cv_basic_types[T_32PINT8] = &symt_new_pointer(module, cv_basic_types[T_INT8])->symt; + cv_basic_types[T_32PUINT8] = &symt_new_pointer(module, cv_basic_types[T_UINT8])->symt; + cv_basic_types[T_32PHRESULT]= &symt_new_pointer(module, cv_basic_types[T_HRESULT])->symt; } static int numeric_leaf(int* value, const unsigned short int* leaf) @@ -391,7 +409,7 @@ static void* codeview_cast_symt(struct symt* symt, enum SymTagEnum tag) } static struct symt* codeview_fetch_type(struct codeview_type_parse* ctp, - unsigned typeno) + unsigned typeno, BOOL details) { struct symt* symt; const union codeview_type* p; @@ -405,7 +423,7 @@ static struct symt* codeview_fetch_type(struct codeview_type_parse* ctp, FIXME("Cannot locate type %x\n", typeno); return NULL; } - symt = codeview_parse_one_type(ctp, typeno, p, FALSE); + symt = codeview_parse_one_type(ctp, typeno, p, details); if (!symt) FIXME("Couldn't load forward type %x\n", typeno); return symt; } @@ -421,7 +439,7 @@ static struct symt* codeview_add_type_pointer(struct codeview_type_parse* ctp, existing = codeview_cast_symt(existing, SymTagPointerType); return existing; } - pointee = codeview_fetch_type(ctp, pointee_type); + pointee = codeview_fetch_type(ctp, pointee_type, FALSE); return &symt_new_pointer(ctp->module, pointee)->symt; } @@ -431,8 +449,8 @@ static struct symt* codeview_add_type_array(struct codeview_type_parse* ctp, unsigned int indextype, unsigned int arr_len) { - struct symt* elem = codeview_fetch_type(ctp, elemtype); - struct symt* index = codeview_fetch_type(ctp, indextype); + struct symt* elem = codeview_fetch_type(ctp, elemtype, FALSE); + struct symt* index = codeview_fetch_type(ctp, indextype, FALSE); DWORD arr_max = 0; if (elem) @@ -504,19 +522,19 @@ static void codeview_add_udt_element(struct codeview_type_parse* ctp, { case LF_BITFIELD_V1: symt_add_udt_element(ctp->module, symt, name, - codeview_fetch_type(ctp, cv_type->bitfield_v1.type), + codeview_fetch_type(ctp, cv_type->bitfield_v1.type, FALSE), cv_type->bitfield_v1.bitoff, cv_type->bitfield_v1.nbits); return; case LF_BITFIELD_V2: symt_add_udt_element(ctp->module, symt, name, - codeview_fetch_type(ctp, cv_type->bitfield_v2.type), + codeview_fetch_type(ctp, cv_type->bitfield_v2.type, FALSE), cv_type->bitfield_v2.bitoff, cv_type->bitfield_v2.nbits); return; } } - subtype = codeview_fetch_type(ctp, type); + subtype = codeview_fetch_type(ctp, type, FALSE); if (subtype) { @@ -641,6 +659,11 @@ static int codeview_add_type_struct_field_list(struct codeview_type_parse* ctp, ptr += 2 + 4 + 2 + (1 + type->stmember_v2.p_name.namelen); break; + case LF_STMEMBER_V3: + /* FIXME: ignored for now */ + ptr += 2 + 4 + 2 + (strlen(type->stmember_v3.name) + 1); + break; + case LF_METHOD_V1: /* FIXME: ignored for now */ ptr += 2 + 2 + 2 + (1 + type->method_v1.p_name.namelen); @@ -651,6 +674,11 @@ static int codeview_add_type_struct_field_list(struct codeview_type_parse* ctp, ptr += 2 + 2 + 4 + (1 + type->method_v2.p_name.namelen); break; + case LF_METHOD_V3: + /* FIXME: ignored for now */ + ptr += 2 + 2 + 4 + (strlen(type->method_v3.name) + 1); + break; + case LF_NESTTYPE_V1: /* FIXME: ignored for now */ ptr += 2 + 2 + (1 + type->nesttype_v1.p_name.namelen); @@ -661,6 +689,11 @@ static int codeview_add_type_struct_field_list(struct codeview_type_parse* ctp, ptr += 2 + 2 + 4 + (1 + type->nesttype_v2.p_name.namelen); break; + case LF_NESTTYPE_V3: + /* FIXME: ignored for now */ + ptr += 2 + 2 + 4 + (strlen(type->nesttype_v3.name) + 1); + break; + case LF_VFUNCTAB_V1: /* FIXME: ignored for now */ ptr += 2 + 2; @@ -699,6 +732,20 @@ static int codeview_add_type_struct_field_list(struct codeview_type_parse* ctp, } break; + case LF_ONEMETHOD_V3: + /* FIXME: ignored for now */ + switch ((type->onemethod_v3.attribute >> 2) & 7) + { + case 4: case 6: /* (pure) introducing virtual method */ + ptr += 2 + 2 + 4 + 4 + (strlen(type->onemethod_virt_v3.name) + 1); + break; + + default: + ptr += 2 + 2 + 4 + (strlen(type->onemethod_v3.name) + 1); + break; + } + break; + default: FIXME("Unsupported type %04x in STRUCT field list\n", type->generic.id); return FALSE; @@ -711,7 +758,8 @@ static int codeview_add_type_struct_field_list(struct codeview_type_parse* ctp, static struct symt* codeview_add_type_enum(struct codeview_type_parse* ctp, struct symt* existing, const char* name, - unsigned fieldlistno) + unsigned fieldlistno, + unsigned basetype) { struct symt_enum* symt; @@ -722,7 +770,8 @@ static struct symt* codeview_add_type_enum(struct codeview_type_parse* ctp, } else { - symt = symt_new_enum(ctp->module, name); + symt = symt_new_enum(ctp->module, name, + codeview_fetch_type(ctp, basetype, FALSE)); if (fieldlistno) { const union codeview_reftype* fieldlist; @@ -775,7 +824,7 @@ static void codeview_add_func_signature_args(struct codeview_type_parse* ctp, { const union codeview_reftype* reftype; - sym->rettype = codeview_fetch_type(ctp, ret_type); + sym->rettype = codeview_fetch_type(ctp, ret_type, FALSE); if (args_list && (reftype = codeview_jump_to_type(ctp, args_list))) { int i; @@ -784,12 +833,12 @@ static void codeview_add_func_signature_args(struct codeview_type_parse* ctp, case LF_ARGLIST_V1: for (i = 0; i < reftype->arglist_v1.num; i++) symt_add_function_signature_parameter(ctp->module, sym, - codeview_fetch_type(ctp, reftype->arglist_v1.args[i])); + codeview_fetch_type(ctp, reftype->arglist_v1.args[i], FALSE)); break; case LF_ARGLIST_V2: for (i = 0; i < reftype->arglist_v2.num; i++) symt_add_function_signature_parameter(ctp->module, sym, - codeview_fetch_type(ctp, reftype->arglist_v2.args[i])); + codeview_fetch_type(ctp, reftype->arglist_v2.args[i], FALSE)); break; default: FIXME("Unexpected leaf %x for signature's pmt\n", reftype->generic.id); @@ -812,8 +861,8 @@ static struct symt* codeview_parse_one_type(struct codeview_type_parse* ctp, switch (type->generic.id) { case LF_MODIFIER_V1: - /* FIXME: we don't handle modifiers, - * but readd previous type on the curr_type + /* FIXME: we don't handle modifiers, + * but read previous type on the curr_type */ WARN("Modifier on %x: %s%s%s%s\n", type->modifier_v1.type, @@ -821,9 +870,7 @@ static struct symt* codeview_parse_one_type(struct codeview_type_parse* ctp, type->modifier_v1.attribute & 0x02 ? "volatile " : "", type->modifier_v1.attribute & 0x04 ? "unaligned " : "", type->modifier_v1.attribute & ~0x07 ? "unknown " : ""); - if (!(symt = codeview_get_type(type->modifier_v1.type, TRUE))) - symt = codeview_parse_one_type(ctp, type->modifier_v1.type, - codeview_jump_to_type(ctp, type->modifier_v1.type), details); + symt = codeview_fetch_type(ctp, type->modifier_v1.type, details); break; case LF_MODIFIER_V2: /* FIXME: we don't handle modifiers, but readd previous type on the curr_type */ @@ -833,9 +880,7 @@ static struct symt* codeview_parse_one_type(struct codeview_type_parse* ctp, type->modifier_v2.attribute & 0x02 ? "volatile " : "", type->modifier_v2.attribute & 0x04 ? "unaligned " : "", type->modifier_v2.attribute & ~0x07 ? "unknown " : ""); - if (!(symt = codeview_get_type(type->modifier_v2.type, TRUE))) - symt = codeview_parse_one_type(ctp, type->modifier_v2.type, - codeview_jump_to_type(ctp, type->modifier_v2.type), details); + symt = codeview_fetch_type(ctp, type->modifier_v2.type, details); break; case LF_POINTER_V1: @@ -965,18 +1010,21 @@ static struct symt* codeview_parse_one_type(struct codeview_type_parse* ctp, case LF_ENUM_V1: symt = codeview_add_type_enum(ctp, existing, terminate_string(&type->enumeration_v1.p_name), - type->enumeration_v1.fieldlist); + type->enumeration_v1.fieldlist, + type->enumeration_v1.type); break; case LF_ENUM_V2: symt = codeview_add_type_enum(ctp, existing, terminate_string(&type->enumeration_v2.p_name), - type->enumeration_v2.fieldlist); + type->enumeration_v2.fieldlist, + type->enumeration_v2.type); break; case LF_ENUM_V3: symt = codeview_add_type_enum(ctp, existing, type->enumeration_v3.name, - type->enumeration_v3.fieldlist); + type->enumeration_v3.fieldlist, + type->enumeration_v3.type); break; case LF_PROCEDURE_V1: @@ -1068,8 +1116,8 @@ static int codeview_parse_type_table(struct codeview_type_parse* ctp) * X 1500-150d for V3 types * 8000-8010 for numeric leafes */ - if (type->generic.id & 0x8600) continue; - codeview_parse_one_type(ctp, curr_type, type, TRUE); + if (!(type->generic.id & 0x8600) || (type->generic.id & 0x0100)) + codeview_parse_one_type(ctp, curr_type, type, TRUE); } return TRUE; @@ -1433,6 +1481,17 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root codeview_get_type(sym->stack_v3.symtype, FALSE), sym->stack_v3.name); break; + case S_BPREL_XXXX_V3: + loc.kind = loc_regrel; + loc.reg = 0; /* FIXME */ + loc.offset = sym->stack_xxxx_v3.offset; + WARN("Supposed stack variable %s (%d)\n", sym->stack_xxxx_v3.name, sym->stack_xxxx_v3.unknown); + symt_add_func_local(msc_dbg->module, curr_func, + sym->stack_xxxx_v3.offset > 0 ? DataIsParam : DataIsLocal, + &loc, block, + codeview_get_type(sym->stack_xxxx_v3.symtype, FALSE), + sym->stack_xxxx_v3.name); + break; case S_REGISTER_V1: loc.kind = loc_register; @@ -1452,6 +1511,15 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root block, codeview_get_type(sym->register_v2.type, FALSE), terminate_string(&sym->register_v2.p_name)); break; + case S_REGISTER_V3: + loc.kind = loc_register; + loc.reg = sym->register_v3.reg; + loc.offset = 0; + symt_add_func_local(msc_dbg->module, curr_func, + DataIsLocal, &loc, + block, codeview_get_type(sym->register_v3.type, FALSE), + sym->register_v3.name); + break; case S_BLOCK_V1: block = symt_open_func_block(msc_dbg->module, curr_func, block, @@ -1525,9 +1593,9 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root symt_add_function_point(msc_dbg->module, curr_func, SymTagLabel, &loc, terminate_string(&sym->label_v1.p_name)); } - else - FIXME("No current function for label %s\n", - terminate_string(&sym->label_v1.p_name)); + else symt_new_label(msc_dbg->module, compiland, + terminate_string(&sym->label_v1.p_name), + codeview_get_address(msc_dbg, sym->label_v1.segment, sym->label_v1.offset)); break; case S_LABEL_V3: if (curr_func) @@ -1537,8 +1605,8 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root symt_add_function_point(msc_dbg->module, curr_func, SymTagLabel, &loc, sym->label_v3.name); } - else - FIXME("No current function for label %s\n", sym->label_v3.name); + else symt_new_label(msc_dbg->module, compiland, sym->label_v3.name, + codeview_get_address(msc_dbg, sym->label_v3.segment, sym->label_v3.offset)); break; case S_CONSTANT_V1: @@ -1651,6 +1719,8 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root break; case S_PUB_FUNC1_V3: case S_PUB_FUNC2_V3: /* using a data_v3 isn't what we'd expect */ +#if 0 + /* FIXME: this is plain wrong (from a simple test) */ if (!(dbghelp_options & SYMOPT_NO_PUBLICS)) { symt_new_public(msc_dbg->module, compiland, @@ -1658,6 +1728,7 @@ static int codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* root codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset), 1, TRUE /* FIXME */, TRUE); } +#endif break; case S_MSTOOL_V3: /* just to silence a few warnings */ diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index c17dae6cde0..cc750c6dddf 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -856,7 +856,8 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typ new_dt = &symt_new_function_signature(ptd->module, ref_dt, -1)->symt; break; case 'e': - new_dt = &symt_new_enum(ptd->module, typename)->symt; + stabs_get_basic(ptd, 1 /* int */, &ref_dt); + new_dt = &symt_new_enum(ptd->module, typename, ref_dt)->symt; PTS_ABORTIF(ptd, stabs_pts_read_enum(ptd, (struct symt_enum*)new_dt) == -1); break; case 's': @@ -910,7 +911,8 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typ switch (tmp) { case 'e': - new_dt = &symt_new_enum(ptd->module, ptd->buf + idx)->symt; + stabs_get_basic(ptd, 1 /* int */, &ref_dt); + new_dt = &symt_new_enum(ptd->module, ptd->buf + idx, ref_dt)->symt; break; case 's': new_dt = &symt_new_udt(ptd->module, ptd->buf + idx, 0, UdtStruct)->symt; diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index d76811b114d..1d7edb8463d 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -374,21 +374,21 @@ struct symt_block* symt_close_func_block(struct module* module, GET_ENTRY(block->container, struct symt_block, symt) : NULL; } -struct symt_function_point* symt_add_function_point(struct module* module, - struct symt_function* func, - enum SymTagEnum point, - const struct location* loc, - const char* name) +struct symt_hierarchy_point* symt_add_function_point(struct module* module, + struct symt_function* func, + enum SymTagEnum point, + const struct location* loc, + const char* name) { - struct symt_function_point* sym; + struct symt_hierarchy_point*sym; struct symt** p; if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) { sym->symt.tag = point; - sym->parent = func; + sym->parent = &func->symt; sym->loc = *loc; - sym->name = name ? pool_strdup(&module->pool, name) : NULL; + sym->hash_elt.name = name ? pool_strdup(&module->pool, name) : NULL; p = vector_add(&func->vchildren, &module->pool); *p = &sym->symt; } @@ -478,6 +478,34 @@ struct symt_data* symt_new_constant(struct module* module, return sym; } +struct symt_hierarchy_point* symt_new_label(struct module* module, + struct symt_compiland* compiland, + const char* name, unsigned long address) +{ + struct symt_hierarchy_point* sym; + + TRACE_(dbghelp_symt)("Adding global label value %s:%s\n", + debugstr_w(module->module.ModuleName), name); + + if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) + { + sym->symt.tag = SymTagLabel; + sym->hash_elt.name = pool_strdup(&module->pool, name); + hash_table_add(&module->ht_symbols, &sym->hash_elt); + module->sortlist_valid = FALSE; + sym->loc.kind = loc_absolute; + sym->loc.offset = address; + sym->parent = compiland ? &compiland->symt : NULL; + if (compiland) + { + struct symt** p; + p = vector_add(&compiland->vchildren, &module->pool); + *p = &sym->symt; + } + } + return sym; +} + /* expect sym_info->MaxNameLen to be set before being called */ static void symt_fill_sym_info(const struct module_pair* pair, const struct symt_function* func, @@ -589,8 +617,8 @@ static void symt_fill_sym_info(const struct module_pair* pair, if (sym_info->MaxNameLen) { if (sym->tag != SymTagPublicSymbol || !(dbghelp_options & SYMOPT_UNDNAME) || - (sym_info->NameLen = UnDecorateSymbolName(name, sym_info->Name, - sym_info->MaxNameLen, UNDNAME_COMPLETE) == 0)) + (sym_info->NameLen = UnDecorateSymbolName(name, sym_info->Name, + sym_info->MaxNameLen, UNDNAME_NAME_ONLY) == 0)) { sym_info->NameLen = min(strlen(name), sym_info->MaxNameLen - 1); memcpy(sym_info->Name, name, sym_info->NameLen); diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index a8c6778ed90..7978a1c5590 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -83,7 +83,7 @@ const char* symt_get_name(const struct symt* sym) case SymTagFunction: return ((const struct symt_function*)sym)->hash_elt.name; case SymTagPublicSymbol: return ((const struct symt_public*)sym)->hash_elt.name; case SymTagBaseType: return ((const struct symt_basic*)sym)->hash_elt.name; - case SymTagLabel: return ((const struct symt_function_point*)sym)->name; + case SymTagLabel: return ((const struct symt_hierarchy_point*)sym)->hash_elt.name; case SymTagThunk: return ((const struct symt_thunk*)sym)->hash_elt.name; /* hierarchy tree */ case SymTagEnum: return ((const struct symt_enum*)sym)->name; @@ -243,7 +243,8 @@ BOOL symt_add_udt_element(struct module* module, struct symt_udt* udt_type, return TRUE; } -struct symt_enum* symt_new_enum(struct module* module, const char* typename) +struct symt_enum* symt_new_enum(struct module* module, const char* typename, + struct symt* basetype) { struct symt_enum* sym; @@ -251,6 +252,7 @@ struct symt_enum* symt_new_enum(struct module* module, const char* typename) { sym->symt.tag = SymTagEnum; sym->name = (typename) ? pool_strdup(&module->pool, typename) : NULL; + sym->base_type = basetype; vector_init(&sym->vchildren, sizeof(struct symt*), 8); } return sym; @@ -271,8 +273,7 @@ BOOL symt_add_enum_element(struct module* module, struct symt_enum* enum_type, e->hash_elt.next = NULL; e->kind = DataIsConstant; e->container = &enum_type->symt; - /* CV defines the underlying type for the enumeration */ - e->type = &symt_new_basic(module, btInt, "int", 4)->symt; + e->type = enum_type->base_type; e->u.value.n1.n2.vt = VT_I4; e->u.value.n1.n2.n3.lVal = value; @@ -518,8 +519,10 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req, case SymTagFuncDebugStart: case SymTagFuncDebugEnd: case SymTagLabel: - X(ULONG64) = ((const struct symt_function_point*)type)->parent->address + - ((const struct symt_function_point*)type)->loc.offset; + if (!symt_get_info(((const struct symt_hierarchy_point*)type)->parent, + req, pInfo)) + return FALSE; + X(ULONG64) += ((const struct symt_hierarchy_point*)type)->loc.offset; break; case SymTagThunk: X(ULONG64) = ((const struct symt_thunk*)type)->address; @@ -648,6 +651,9 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req, case SymTagThunk: X(DWORD64) = ((const struct symt_thunk*)type)->size; break; + case SymTagLabel: + X(DWORD64) = 0; + break; default: FIXME("Unsupported sym-tag %s for get-length\n", symt_get_tag_str(type->tag)); @@ -759,7 +765,9 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req, case SymTagFunction: X(DWORD) = (DWORD)((const struct symt_function*)type)->type; break; - /* FIXME: should also work for enums */ + case SymTagEnum: + X(DWORD) = (DWORD)((const struct symt_enum*)type)->base_type; + break; case SymTagFunctionArgType: X(DWORD) = (DWORD)((const struct symt_function_arg_type*)type)->arg_type; break; @@ -768,6 +776,7 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req, symt_get_tag_str(type->tag)); case SymTagPublicSymbol: case SymTagThunk: + case SymTagLabel: return FALSE; } break; @@ -797,10 +806,15 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req, X(DWORD) = (DWORD)((const struct symt_array*)type)->index_type; break; + case TI_GET_CLASSPARENTID: + /* FIXME: we don't support properly C++ for now, pretend this symbol doesn't + * belong to a parent class + */ + return FALSE; + #undef X case TI_GET_ADDRESSOFFSET: - case TI_GET_CLASSPARENTID: case TI_GET_SYMINDEX: case TI_GET_THISADJUST: case TI_GET_VIRTUALBASECLASS: diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c index d92f36be92d..fb9e51e9061 100644 --- a/dlls/ddraw/tests/d3d.c +++ b/dlls/ddraw/tests/d3d.c @@ -1049,7 +1049,7 @@ static void Direct3D1Test(void) ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y && cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw, - "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1, + "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1, out[i].x, out[i].y, out[i].z, out[i].rhw, cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw); } @@ -1078,7 +1078,7 @@ static void Direct3D1Test(void) }; ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y && cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw, - "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1, + "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1, out[i].x, out[i].y, out[i].z, out[i].rhw, cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw); } @@ -1099,7 +1099,7 @@ static void Direct3D1Test(void) }; ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y && cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw, - "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1, + "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1, out[i].x, out[i].y, out[i].z, out[i].rhw, cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw); } @@ -1118,7 +1118,7 @@ static void Direct3D1Test(void) }; ok(U1(cmpH[i]).hx == U1(outH[i]).hx && U2(cmpH[i]).hy == U2(outH[i]).hy && U3(cmpH[i]).hz == U3(outH[i]).hz && cmpH[i].dwFlags == outH[i].dwFlags, - "HVertex %d differs. Got %08x %f %f %f, expexted %08x %f %f %f\n", i + 1, + "HVertex %d differs. Got %08x %f %f %f, expected %08x %f %f %f\n", i + 1, outH[i].dwFlags, U1(outH[i]).hx, U2(outH[i]).hy, U3(outH[i]).hz, cmpH[i].dwFlags, U1(cmpH[i]).hx, U2(cmpH[i]).hy, U3(cmpH[i]).hz); @@ -1135,7 +1135,7 @@ static void Direct3D1Test(void) }; ok(cmp[i].x == out[i].x && cmp[i].y == out[i].y && cmp[i].z == out[i].z && cmp[i].rhw == out[i].rhw, - "Vertex %d differs. Got %f %f %f %f, expexted %f %f %f %f\n", i + 1, + "Vertex %d differs. Got %f %f %f %f, expected %f %f %f %f\n", i + 1, out[i].x, out[i].y, out[i].z, out[i].rhw, cmp[i].x, cmp[i].y, cmp[i].z, cmp[i].rhw); } @@ -1161,7 +1161,7 @@ static void Direct3D1Test(void) D3DCLIP_LEFT | D3DCLIP_BOTTOM | D3DCLIP_FRONT, }; ok(Flags[i] == outH[i].dwFlags, - "Cliptest %d differs. Got %08x expexted %08x\n", i + 1, + "Cliptest %d differs. Got %08x expected %08x\n", i + 1, outH[i].dwFlags, Flags[i]); } @@ -1184,7 +1184,7 @@ static void Direct3D1Test(void) D3DCLIP_LEFT | D3DCLIP_FRONT, }; ok(Flags[i] == outH[i].dwFlags, - "Cliptest %d differs. Got %08x expexted %08x\n", i + 1, + "Cliptest %d differs. Got %08x expected %08x\n", i + 1, outH[i].dwFlags, Flags[i]); } vp_data.dwWidth = 256; @@ -1207,7 +1207,7 @@ static void Direct3D1Test(void) D3DCLIP_FRONT, }; ok(Flags[i] == outH[i].dwFlags, - "Cliptest %d differs. Got %08x expexted %08x\n", i + 1, + "Cliptest %d differs. Got %08x expected %08x\n", i + 1, outH[i].dwFlags, Flags[i]); } diff --git a/dlls/ddraw/tests/ddrawmodes.c b/dlls/ddraw/tests/ddrawmodes.c index 529c81a2b81..ea8939b600a 100644 --- a/dlls/ddraw/tests/ddrawmodes.c +++ b/dlls/ddraw/tests/ddrawmodes.c @@ -118,11 +118,15 @@ static HRESULT WINAPI enummodescallback(LPDDSURFACEDESC lpddsd, LPVOID lpContext ok(U1(*lpddsd).lPitch != 0, "EnumDisplayModes callback with bad pitch\n"); } - /* Check that frequency is valid if applicable */ + /* Check that frequency is valid if applicable + * + * This fails on some Windows drivers or Windows versions, so it isn't important + * apparently if(lpddsd->dwFlags & DDSD_REFRESHRATE) { ok(U2(*lpddsd).dwRefreshRate != 0, "EnumDisplayModes callback with bad refresh rate\n"); } + */ adddisplaymode(lpddsd); diff --git a/dlls/ddraw/tests/visual.c b/dlls/ddraw/tests/visual.c index eed9bdfa228..1f965e1d29e 100644 --- a/dlls/ddraw/tests/visual.c +++ b/dlls/ddraw/tests/visual.c @@ -989,8 +989,8 @@ out: ptr = ((D3DINSTRUCTION*)(ptr))+1; } while (0) #define EXEBUF_PUT_RENDER_STATE(state, value, ptr) do {\ - ((D3DSTATE*)(ptr))->drstRenderStateType = state;\ - ((D3DSTATE*)(ptr))->dwArg[0] = value;\ + U1(*((D3DSTATE*)(ptr))).drstRenderStateType = state; \ + U2(*((D3DSTATE*)(ptr))).dwArg[0] = value; \ ptr = ((D3DSTATE*)(ptr))+1; } while (0) #define EXEBUF_PUT_PROCESSVERTICES(nvertices, ptr) do {\ @@ -1016,14 +1016,14 @@ out: ((D3DINSTRUCTION*)(ptr))->bSize = sizeof(D3DTRIANGLE);\ ((D3DINSTRUCTION*)(ptr))->wCount = 2;\ ptr = ((D3DINSTRUCTION*)(ptr))+1;\ - ((D3DTRIANGLE*)(ptr))->v1 = base_idx;\ - ((D3DTRIANGLE*)(ptr))->v2 = (base_idx) + 1;\ - ((D3DTRIANGLE*)(ptr))->v3 = (base_idx) + 3;\ + U1(*((D3DTRIANGLE*)(ptr))).v1 = base_idx;\ + U2(*((D3DTRIANGLE*)(ptr))).v2 = (base_idx) + 1; \ + U3(*((D3DTRIANGLE*)(ptr))).v3 = (base_idx) + 3; \ ((D3DTRIANGLE*)(ptr))->wFlags = 0;\ ptr = ((D3DTRIANGLE*)ptr)+1;\ - ((D3DTRIANGLE*)(ptr))->v1 = (base_idx) + 1;\ - ((D3DTRIANGLE*)(ptr))->v2 = (base_idx) + 2;\ - ((D3DTRIANGLE*)(ptr))->v3 = (base_idx) + 3;\ + U1(*((D3DTRIANGLE*)(ptr))).v1 = (base_idx) + 1; \ + U2(*((D3DTRIANGLE*)(ptr))).v2 = (base_idx) + 2; \ + U3(*((D3DTRIANGLE*)(ptr))).v3 = (base_idx) + 3; \ ((D3DTRIANGLE*)(ptr))->wFlags = 0;\ ptr = ((D3DTRIANGLE*)(ptr))+1;\ } while (0) @@ -1103,14 +1103,14 @@ static void D3D1_TextureMapBlendTest(void) memset(&ddbltfx, 0, sizeof(ddbltfx)); ddbltfx.dwSize = sizeof(ddbltfx); - ddbltfx.dwFillColor = 0; + U5(ddbltfx).dwFillColor = 0; hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); - ddbltfx.dwFillColor = 0xff0000ff; + U5(ddbltfx).dwFillColor = 0xff0000ff; hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); - ddbltfx.dwFillColor = 0x800000ff; + U5(ddbltfx).dwFillColor = 0x800000ff; hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); @@ -1235,14 +1235,14 @@ static void D3D1_TextureMapBlendTest(void) memset(&ddbltfx, 0, sizeof(ddbltfx)); ddbltfx.dwSize = sizeof(ddbltfx); - ddbltfx.dwFillColor = 0; + U5(ddbltfx).dwFillColor = 0; hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); - ddbltfx.dwFillColor = 0xff0000ff; + U5(ddbltfx).dwFillColor = 0xff0000ff; hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); - ddbltfx.dwFillColor = 0x800000ff; + U5(ddbltfx).dwFillColor = 0x800000ff; hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); @@ -1356,14 +1356,14 @@ static void D3D1_TextureMapBlendTest(void) memset(&ddbltfx, 0, sizeof(ddbltfx)); ddbltfx.dwSize = sizeof(ddbltfx); - ddbltfx.dwFillColor = 0; + U5(ddbltfx).dwFillColor = 0; hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); - ddbltfx.dwFillColor = 0x00ffffff; + U5(ddbltfx).dwFillColor = 0x00ffffff; hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); - ddbltfx.dwFillColor = 0x00ffff80; + U5(ddbltfx).dwFillColor = 0x00ffff80; hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); @@ -1478,13 +1478,13 @@ static void D3D1_TextureMapBlendTest(void) memset(&ddbltfx, 0, sizeof(ddbltfx)); ddbltfx.dwSize = sizeof(ddbltfx); - ddbltfx.dwFillColor = 0; + U5(ddbltfx).dwFillColor = 0; hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); - ddbltfx.dwFillColor = 0xf800; + U5(ddbltfx).dwFillColor = 0xf800; hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); - ddbltfx.dwFillColor = 0x001f; + U5(ddbltfx).dwFillColor = 0x001f; hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr); diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c index 55b3236c0e2..c46892014fa 100644 --- a/dlls/gdi32/bitmap.c +++ b/dlls/gdi32/bitmap.c @@ -132,13 +132,10 @@ HBITMAP WINAPI CreateBitmap( INT width, INT height, UINT planes, HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height) { HBITMAP hbmpRet = 0; - DC *dc; TRACE("(%p,%d,%d) =\n", hdc, width, height); - if (!(dc = DC_GetDCPtr(hdc))) return 0; - - if (GDIMAGIC( dc->header.wMagic ) != MEMORY_DC_MAGIC) + if (GetObjectType( hdc ) != OBJ_MEMDC) { hbmpRet = CreateBitmap(width, height, GetDeviceCaps(hdc, PLANES), @@ -147,14 +144,18 @@ HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height) } else /* Memory DC */ { - BITMAPOBJ *bmp = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC ); + DIBSECTION dib; + HBITMAP bitmap = GetCurrentObject( hdc, OBJ_BITMAP ); + INT size = GetObjectW( bitmap, sizeof(dib), &dib ); + + if (!size) return 0; - if (!bmp->dib) + if (size == sizeof(BITMAP)) { /* A device-dependent bitmap is selected in the DC */ hbmpRet = CreateBitmap(width, height, - bmp->bitmap.bmPlanes, - bmp->bitmap.bmBitsPixel, + dib.dsBm.bmPlanes, + dib.dsBm.bmBitsPixel, NULL); } else @@ -174,19 +175,19 @@ HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height) bi->bmiHeader.biSize = sizeof(bi->bmiHeader); bi->bmiHeader.biWidth = width; bi->bmiHeader.biHeight = height; - bi->bmiHeader.biPlanes = bmp->dib->dsBmih.biPlanes; - bi->bmiHeader.biBitCount = bmp->dib->dsBmih.biBitCount; - bi->bmiHeader.biCompression = bmp->dib->dsBmih.biCompression; + bi->bmiHeader.biPlanes = dib.dsBmih.biPlanes; + bi->bmiHeader.biBitCount = dib.dsBmih.biBitCount; + bi->bmiHeader.biCompression = dib.dsBmih.biCompression; bi->bmiHeader.biSizeImage = 0; - bi->bmiHeader.biXPelsPerMeter = bmp->dib->dsBmih.biXPelsPerMeter; - bi->bmiHeader.biYPelsPerMeter = bmp->dib->dsBmih.biYPelsPerMeter; - bi->bmiHeader.biClrUsed = bmp->dib->dsBmih.biClrUsed; - bi->bmiHeader.biClrImportant = bmp->dib->dsBmih.biClrImportant; + bi->bmiHeader.biXPelsPerMeter = dib.dsBmih.biXPelsPerMeter; + bi->bmiHeader.biYPelsPerMeter = dib.dsBmih.biYPelsPerMeter; + bi->bmiHeader.biClrUsed = dib.dsBmih.biClrUsed; + bi->bmiHeader.biClrImportant = dib.dsBmih.biClrImportant; if (bi->bmiHeader.biCompression == BI_BITFIELDS) { /* Copy the color masks */ - CopyMemory(bi->bmiColors, bmp->dib->dsBitfields, 3 * sizeof(DWORD)); + CopyMemory(bi->bmiColors, dib.dsBitfields, 3 * sizeof(DWORD)); } else if (bi->bmiHeader.biBitCount <= 8) { @@ -198,9 +199,7 @@ HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height) HeapFree(GetProcessHeap(), 0, bi); } } - GDI_ReleaseObj(dc->hBitmap); } - DC_ReleaseDCPtr( dc ); TRACE("\t\t%p\n", hbmpRet); return hbmpRet; @@ -511,14 +510,10 @@ LONG WINAPI SetBitmapBits( */ HBITMAP BITMAP_CopyBitmap(HBITMAP hbitmap) { - BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ); HBITMAP res = 0; BITMAP bm; - if(!bmp) return 0; - - bm = bmp->bitmap; - bm.bmBits = NULL; + if (!GetObjectW( hbitmap, sizeof(bm), &bm )) return 0; res = CreateBitmapIndirect(&bm); if(res) { @@ -528,8 +523,6 @@ HBITMAP BITMAP_CopyBitmap(HBITMAP hbitmap) SetBitmapBits (res, bm.bmWidthBytes * bm.bmHeight, buf); HeapFree( GetProcessHeap(), 0, buf ); } - - GDI_ReleaseObj( hbitmap ); return res; } @@ -577,13 +570,8 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc ) BITMAPOBJ *bitmap; DC *dc; - if (!(bitmap = GDI_GetObjPtr( handle, BITMAP_MAGIC ))) return 0; + if (!(dc = get_dc_ptr( hdc ))) return 0; - if (!(dc = get_dc_ptr( hdc ))) - { - GDI_ReleaseObj( handle ); - return 0; - } if (GetObjectType( hdc ) != OBJ_MEMDC) { ret = 0; @@ -592,34 +580,44 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc ) ret = dc->hBitmap; if (handle == dc->hBitmap) goto done; /* nothing to do */ + if (!(bitmap = GDI_GetObjPtr( handle, BITMAP_MAGIC ))) + { + ret = 0; + goto done; + } + if (bitmap->header.dwCount && (handle != GetStockObject(DEFAULT_BITMAP))) { WARN( "Bitmap already selected in another DC\n" ); + GDI_ReleaseObj( handle ); ret = 0; goto done; } if (!bitmap->funcs && !BITMAP_SetOwnerDC( handle, dc )) { + GDI_ReleaseObj( handle ); ret = 0; goto done; } - if (dc->funcs->pSelectBitmap) handle = dc->funcs->pSelectBitmap( dc->physDev, handle ); - - if (handle) + if (dc->funcs->pSelectBitmap && !dc->funcs->pSelectBitmap( dc->physDev, handle )) + { + GDI_ReleaseObj( handle ); + ret = 0; + } + else { dc->hBitmap = handle; GDI_inc_ref_count( handle ); dc->dirty = 0; SetRectRgn( dc->hVisRgn, 0, 0, bitmap->bitmap.bmWidth, bitmap->bitmap.bmHeight); + GDI_ReleaseObj( handle ); DC_InitDC( dc ); GDI_dec_ref_count( ret ); } - else ret = 0; done: - GDI_ReleaseObj( handle ); release_dc_ptr( dc ); return ret; } diff --git a/dlls/gdi32/brush.c b/dlls/gdi32/brush.c index c713f746a90..95da9b1c773 100644 --- a/dlls/gdi32/brush.c +++ b/dlls/gdi32/brush.c @@ -336,7 +336,7 @@ HBRUSH WINAPI CreateSolidBrush( COLORREF color ) */ BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg ) { - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (oldorg) @@ -346,7 +346,7 @@ BOOL WINAPI SetBrushOrgEx( HDC hdc, INT x, INT y, LPPOINT oldorg ) } dc->brushOrgX = x; dc->brushOrgY = y; - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return TRUE; } @@ -374,22 +374,30 @@ static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc ) HGDIOBJ ret = 0; DC *dc = get_dc_ptr( hdc ); - if (!dc) return 0; + if (!dc) + { + SetLastError( ERROR_INVALID_HANDLE ); + return 0; + } if ((brush = GDI_GetObjPtr( handle, BRUSH_MAGIC ))) { if (brush->logbrush.lbStyle == BS_PATTERN) BITMAP_SetOwnerDC( (HBITMAP)brush->logbrush.lbHatch, dc ); - if (dc->funcs->pSelectBrush) handle = dc->funcs->pSelectBrush( dc->physDev, handle ); - if (handle) + GDI_inc_ref_count( handle ); + GDI_ReleaseObj( handle ); + + if (dc->funcs->pSelectBrush && !dc->funcs->pSelectBrush( dc->physDev, handle )) + { + GDI_dec_ref_count( handle ); + } + else { ret = dc->hBrush; dc->hBrush = handle; - GDI_inc_ref_count( handle ); GDI_dec_ref_count( ret ); } - GDI_ReleaseObj( handle ); } release_dc_ptr( dc ); return ret; diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 161e0df0bc6..ba59a8d5664 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -156,40 +156,6 @@ DC *alloc_dc_ptr( const DC_FUNCTIONS *funcs, WORD magic ) /*********************************************************************** - * DC_GetDCPtr - */ -DC *DC_GetDCPtr( HDC hdc ) -{ - DC *dc = get_dc_obj( hdc ); - if (!dc) return NULL; - - if (!InterlockedCompareExchange( &dc->refcount, 1, 0 )) - { - dc->thread = GetCurrentThreadId(); - } - else if (dc->thread != GetCurrentThreadId()) - { - GDI_ReleaseObj( hdc ); - SetLastError( ERROR_ACCESS_DENIED ); - return NULL; - } - else InterlockedIncrement( &dc->refcount ); - - return dc; -} - - -/*********************************************************************** - * DC_ReleaseDCPtr - */ -void DC_ReleaseDCPtr( DC *dc ) -{ - release_dc_ptr( dc ); - GDI_ReleaseObj( dc->hSelf ); -} - - -/*********************************************************************** * free_dc_ptr */ BOOL free_dc_ptr( DC *dc ) diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c index 9f7aa4e8f72..e8b3dc92200 100644 --- a/dlls/gdi32/dib.c +++ b/dlls/gdi32/dib.c @@ -376,7 +376,7 @@ UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUA UINT result = 0; BITMAPOBJ * bitmap; - if (!(dc = DC_GetDCPtr( hdc ))) return 0; + if (!(dc = get_dc_ptr( hdc ))) return 0; if ((bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC ))) { @@ -396,7 +396,7 @@ UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUA if (dc->funcs->pSetDIBColorTable) dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return result; } @@ -409,7 +409,7 @@ UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *col DC * dc; UINT result = 0; - if (!(dc = DC_GetDCPtr( hdc ))) return 0; + if (!(dc = get_dc_ptr( hdc ))) return 0; if (dc->funcs->pGetDIBColorTable) result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors); @@ -431,7 +431,7 @@ UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *col GDI_ReleaseObj( dc->hBitmap ); } } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return result; } @@ -1075,14 +1075,14 @@ HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header, { if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse ); - else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) ) + else if (hdc && ((dc = get_dc_ptr( hdc )) != NULL) ) { if (!BITMAP_SetOwnerDC( handle, dc )) { DeleteObject( handle ); handle = 0; } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); } } @@ -1323,7 +1323,7 @@ HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage, bDesktopDC = TRUE; } - if (!(dc = DC_GetDCPtr( hdc ))) goto error; + if (!(dc = get_dc_ptr( hdc ))) goto error; /* create Device Dependent Bitmap and add DIB pointer */ ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1, @@ -1347,7 +1347,7 @@ HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage, } } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); if (bDesktopDC) DeleteDC( hdc ); if (ret && bits) *bits = dib->dsBm.bmBits; return ret; diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 5cec471011b..28853fbabeb 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -123,8 +123,6 @@ typedef struct SEGPTR segLogFont; DWORD dwFlags; HDC hdc; - DC *dc; - PHYSDEV physDev; } fontEnum16; typedef struct @@ -134,8 +132,6 @@ typedef struct LPARAM lpData; DWORD dwFlags; HDC hdc; - DC *dc; - PHYSDEV physDev; } fontEnum32; /* @@ -690,7 +686,6 @@ static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW { fontEnum16 *pfe = (fontEnum16*)lp; INT ret = 1; - DC *dc; if (!pfe->lpLogFontParam || pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET || @@ -702,7 +697,6 @@ static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont); FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric); pfe->dwFlags |= ENUM_CALLED; - DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */ args[6] = SELECTOROF(pfe->segLogFont); args[5] = OFFSETOF(pfe->segLogFont); @@ -713,16 +707,6 @@ static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW args[0] = LOWORD(pfe->lpData); WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result ); ret = LOWORD(result); - - /* get the lock again and make sure the DC is still valid */ - dc = DC_GetDCPtr( pfe->hdc ); - if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev) - { - if (dc) DC_ReleaseDCPtr( dc ); - pfe->hdc = 0; /* make sure we don't try to release it later on */ - pfe->dc = NULL; - ret = 0; - } } return ret; } @@ -738,7 +722,6 @@ static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *p { fontEnum32 *pfe = (fontEnum32*)lp; INT ret = 1; - DC *dc; /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */ if ((!pfe->lpLogFontParam || @@ -758,19 +741,8 @@ static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *p plf = (LOGFONTW *)&logfont.elfLogFont; ptm = (TEXTMETRICW *)&tmA; } - DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */ ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData ); - - /* get the lock again and make sure the DC is still valid */ - dc = DC_GetDCPtr( pfe->hdc ); - if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev) - { - if (dc) DC_ReleaseDCPtr( dc ); - pfe->hdc = 0; /* make sure we don't try to release it later on */ - pfe->dc = NULL; - ret = 0; - } } return ret; } @@ -784,7 +756,7 @@ INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf, { fontEnum16 fe16; INT16 ret = 1, ret2; - DC* dc = DC_GetDCPtr( HDC_32(hDC) ); + DC* dc = get_dc_ptr( HDC_32(hDC) ); NEWTEXTMETRICEX16 tm16; ENUMLOGFONTEX16 lf16; LOGFONTW lfW, *plfW; @@ -800,8 +772,6 @@ INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf, else plfW = NULL; fe16.hdc = HDC_32(hDC); - fe16.dc = dc; - fe16.physDev = dc->physDev; fe16.lpLogFontParam = plf; fe16.lpEnumFunc = efproc; fe16.lpData = lParam; @@ -830,7 +800,7 @@ INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf, done: UnMapLS( fe16.segTextMetric ); UnMapLS( fe16.segLogFont ); - if (fe16.dc) DC_ReleaseDCPtr( fe16.dc ); + release_dc_ptr( dc ); return ret; } @@ -842,7 +812,7 @@ static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, LPARAM lParam, DWORD dwUnicode) { INT ret = 1, ret2; - DC *dc = DC_GetDCPtr( hDC ); + DC *dc = get_dc_ptr( hDC ); fontEnum32 fe32; BOOL enum_gdi_fonts; @@ -856,8 +826,6 @@ static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, fe32.lpData = lParam; fe32.dwFlags = dwUnicode; fe32.hdc = hDC; - fe32.dc = dc; - fe32.physDev = dc->physDev; enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE; @@ -876,7 +844,7 @@ static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, ret = ret2; } done: - if (fe32.dc) DC_ReleaseDCPtr( fe32.dc ); + release_dc_ptr( dc ); return ret; } @@ -1006,10 +974,10 @@ INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc, INT WINAPI GetTextCharacterExtra( HDC hdc ) { INT ret; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if (!dc) return 0x80000000; ret = dc->charExtra; - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -1020,7 +988,7 @@ INT WINAPI GetTextCharacterExtra( HDC hdc ) INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra ) { INT prev; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return 0x80000000; if (dc->funcs->pSetTextCharacterExtra) prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra ); @@ -1029,7 +997,7 @@ INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra ) prev = dc->charExtra; dc->charExtra = extra; } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return prev; } @@ -1040,7 +1008,7 @@ INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra ) BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks ) { BOOL ret = TRUE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->funcs->pSetTextJustification) ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks ); @@ -1059,7 +1027,7 @@ BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks ) dc->breakRem = 0; } } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -1093,7 +1061,7 @@ INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name ) FONTOBJ *font; INT ret = 0; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return 0; if(dc->gdiFont) @@ -1108,7 +1076,7 @@ INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name ) else ret = strlenW(font->logfont.lfFaceName) + 1; GDI_ReleaseObj( dc->hFont ); } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -1178,7 +1146,7 @@ BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT LPINT nfit, LPINT dxs, LPSIZE size ) { BOOL ret = FALSE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if(dc->gdiFont) { @@ -1193,7 +1161,7 @@ BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT count, max_ext, nfit, dxs, size ); } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); TRACE("(%p %p %d %p): returning %d x %d\n", hdc, indices, count, size, size->cx, size->cy ); @@ -1320,7 +1288,7 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count, TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt); - dc = DC_GetDCPtr(hdc); + dc = get_dc_ptr(hdc); if (! dc) return FALSE; @@ -1333,7 +1301,7 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count, dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]); if (! dxs) { - DC_ReleaseDCPtr(dc); + release_dc_ptr(dc); SetLastError(ERROR_OUTOFMEMORY); return FALSE; } @@ -1402,7 +1370,7 @@ BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count, if (! alpDx) HeapFree(GetProcessHeap(), 0, dxs); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy); return ret; @@ -1426,7 +1394,7 @@ BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics ) BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics ) { BOOL ret = FALSE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->gdiFont) @@ -1481,7 +1449,7 @@ BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics ) metrics->tmDescent, metrics->tmHeight ); } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -1690,7 +1658,7 @@ UINT WINAPI GetOutlineTextMetricsW( UINT cbData, /* [in] Size of metric data array */ LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */ { - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); OUTLINETEXTMETRICW *output = lpOTM; UINT ret; @@ -1772,7 +1740,7 @@ UINT WINAPI GetOutlineTextMetricsW( } } } - DC_ReleaseDCPtr(dc); + release_dc_ptr(dc); return ret; } @@ -1786,7 +1754,7 @@ BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar, { UINT i; BOOL ret = FALSE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->gdiFont) @@ -1801,7 +1769,7 @@ BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar, *buffer = INTERNAL_XDSTOWS(dc, *buffer); ret = TRUE; } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -2425,7 +2393,7 @@ BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings ) */ DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag ) { - DC *dc = DC_GetDCPtr( hDC ); + DC *dc = get_dc_ptr( hDC ); DWORD ret = 0; if(!dc) return 0; if(dc->funcs->pSetMapperFlags) @@ -2435,7 +2403,7 @@ DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag ) } else FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -2517,7 +2485,7 @@ BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar, BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar, LPABC abc ) { - DC *dc = DC_GetDCPtr(hdc); + DC *dc = get_dc_ptr(hdc); unsigned int i; BOOL ret = FALSE; @@ -2525,7 +2493,7 @@ BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar, if (!abc) { - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return FALSE; } @@ -2545,7 +2513,7 @@ BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar, ret = TRUE; } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -2572,7 +2540,7 @@ BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar, BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count, LPWORD pgi, LPABC abc) { - DC *dc = DC_GetDCPtr(hdc); + DC *dc = get_dc_ptr(hdc); unsigned int i; BOOL ret = FALSE; @@ -2580,7 +2548,7 @@ BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count, if (!abc) { - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return FALSE; } @@ -2600,7 +2568,7 @@ BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count, ret = TRUE; } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -2644,7 +2612,7 @@ DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPVOID lpBuffer, const MAT2 *lpmat2 ) { - DC *dc = DC_GetDCPtr(hdc); + DC *dc = get_dc_ptr(hdc); DWORD ret; TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n", @@ -2658,7 +2626,7 @@ DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat, else ret = GDI_ERROR; - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -2791,13 +2759,13 @@ DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs, return 0; } - dc = DC_GetDCPtr(hDC); + dc = get_dc_ptr(hDC); if (!dc) return 0; if (dc->gdiFont) ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -2912,7 +2880,7 @@ DWORD WINAPI GetFontLanguageInfo(HDC hdc) DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset, LPVOID buffer, DWORD length) { - DC *dc = DC_GetDCPtr(hdc); + DC *dc = get_dc_ptr(hdc); DWORD ret = GDI_ERROR; if(!dc) return GDI_ERROR; @@ -2920,7 +2888,7 @@ DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset, if(dc->gdiFont) ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -2950,7 +2918,7 @@ DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count, DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count, LPWORD pgi, DWORD flags) { - DC *dc = DC_GetDCPtr(hdc); + DC *dc = get_dc_ptr(hdc); DWORD ret = GDI_ERROR; TRACE("(%p, %s, %d, %p, 0x%x)\n", @@ -2961,7 +2929,7 @@ DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count, if(dc->gdiFont) ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -3367,14 +3335,14 @@ UINT WINAPI GetTextCharset(HDC hdc) UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags) { UINT ret = DEFAULT_CHARSET; - DC *dc = DC_GetDCPtr(hdc); + DC *dc = get_dc_ptr(hdc); if (dc) { if (dc->gdiFont) ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); } if (ret == DEFAULT_CHARSET && fs) @@ -3487,14 +3455,14 @@ BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs) { DWORD ret = 0; - DC *dc = DC_GetDCPtr(hdc); + DC *dc = get_dc_ptr(hdc); TRACE("(%p, %p)\n", hdc, lpgs); if (!dc) return 0; if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs); - DC_ReleaseDCPtr(dc); + release_dc_ptr(dc); return ret; } @@ -3504,12 +3472,12 @@ DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs) */ BOOL WINAPI FontIsLinked(HDC hdc) { - DC *dc = DC_GetDCPtr(hdc); + DC *dc = get_dc_ptr(hdc); BOOL ret = FALSE; if (!dc) return FALSE; if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont); - DC_ReleaseDCPtr(dc); + release_dc_ptr(dc); TRACE("returning %d\n", ret); return ret; } diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 4b54699fbce..08e6638d605 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -309,6 +309,15 @@ typedef struct { struct tagGdiFont { struct list entry; + GM **gm; + DWORD gmsize; + struct list hfontlist; + OUTLINETEXTMETRICW *potm; + DWORD total_kern_pairs; + KERNINGPAIR *kern_pairs; + struct list child_fonts; + + /* the following members can be accessed without locking, they are never modified after creation */ FT_Face ft_face; struct font_mapping *mapping; LPWSTR name; @@ -319,21 +328,14 @@ struct tagGdiFont { BYTE underline; BYTE strikeout; INT orientation; - GM **gm; - DWORD gmsize; - struct list hfontlist; FONT_DESC font_desc; LONG aveWidth, ppem; float scale_y; SHORT yMax; SHORT yMin; - OUTLINETEXTMETRICW *potm; DWORD ntmFlags; - DWORD total_kern_pairs; - KERNINGPAIR *kern_pairs; FONTSIGNATURE fs; GdiFont *base_font; - struct list child_fonts; }; typedef struct { @@ -453,6 +455,15 @@ static struct list mappings_list = LIST_INIT( mappings_list ); static BOOL have_installed_roman_font = FALSE; /* CreateFontInstance will fail if this is still FALSE */ +static CRITICAL_SECTION freetype_cs; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &freetype_cs, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": freetype_cs") } +}; +static CRITICAL_SECTION freetype_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; + static const WCHAR font_mutex_nameW[] = {'_','_','W','I','N','E','_','F','O','N','T','_','M','U','T','E','X','_','_','\0'}; static BOOL get_glyph_index_linked(GdiFont *font, UINT c, GdiFont **linked_font, FT_UInt *glyph); @@ -1678,7 +1689,9 @@ static BOOL load_font_from_data_dir(LPCWSTR file) WideCharToMultiByte(CP_UNIXCP, 0, file, -1, unix_name + strlen(unix_name), len, NULL, NULL); + EnterCriticalSection( &freetype_cs ); ret = AddFontFileToList(unix_name, NULL, NULL, ADDFONT_FORCE_BITMAP); + LeaveCriticalSection( &freetype_cs ); HeapFree(GetProcessHeap(), 0, unix_name); } return ret; @@ -1696,7 +1709,9 @@ static BOOL load_font_from_winfonts_dir(LPCWSTR file) strcatW(windowsdir, slashW); strcatW(windowsdir, file); if ((unixname = wine_get_unix_file_name(windowsdir))) { + EnterCriticalSection( &freetype_cs ); ret = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP); + LeaveCriticalSection( &freetype_cs ); HeapFree(GetProcessHeap(), 0, unixname); } return ret; @@ -1857,7 +1872,9 @@ INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv) if((unixname = wine_get_unix_file_name(file))) { + EnterCriticalSection( &freetype_cs ); ret = AddFontFileToList(unixname, NULL, NULL, ADDFONT_FORCE_BITMAP); + LeaveCriticalSection( &freetype_cs ); HeapFree(GetProcessHeap(), 0, unixname); } if (!ret && !strchrW(file, '\\')) { @@ -1887,7 +1904,9 @@ HANDLE WineEngAddFontMemResourceEx(PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD TRACE("Copying %d bytes of data from %p to %p\n", cbFont, pbFont, pFontCopy); memcpy(pFontCopy, pbFont, cbFont); + EnterCriticalSection( &freetype_cs ); *pcFonts = AddFontToList(NULL, pFontCopy, cbFont, NULL, NULL, ADDFONT_FORCE_BITMAP); + LeaveCriticalSection( &freetype_cs ); if (*pcFonts == 0) { @@ -2717,7 +2736,7 @@ static LONG load_VDMX(GdiFont *font, LONG height) return ppem; } -static BOOL fontcmp(GdiFont *font, FONT_DESC *fd) +static BOOL fontcmp(const GdiFont *font, FONT_DESC *fd) { if(font->font_desc.hash != fd->hash) return TRUE; if(memcmp(&font->font_desc.matrix, &fd->matrix, sizeof(fd->matrix))) return TRUE; @@ -2904,15 +2923,24 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) CHARSETINFO csi; HFONTLIST *hflist; + EnterCriticalSection( &freetype_cs ); + LIST_FOR_EACH_ENTRY(ret, &child_font_list, struct tagGdiFont, entry) { struct list *first_hfont = list_head(&ret->hfontlist); hflist = LIST_ENTRY(first_hfont, HFONTLIST, entry); if(hflist->hfont == hfont) + { + LeaveCriticalSection( &freetype_cs ); return ret; + } } - if (!GetObjectW( hfont, sizeof(lf), &lf )) return NULL; + if (!GetObjectW( hfont, sizeof(lf), &lf )) + { + LeaveCriticalSection( &freetype_cs ); + return NULL; + } can_use_bitmap = GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_RA_ABLE; TRACE("%s, h=%d, it=%d, weight=%d, PandF=%02x, charset=%d orient %d escapement %d\n", @@ -2923,6 +2951,7 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) /* check the cache first */ if((ret = find_in_cache(hfont, &lf, &dc->xformWorld2Vport, can_use_bitmap)) != NULL) { TRACE("returning cached gdiFont(%p) for hFont %p\n", ret, hfont); + LeaveCriticalSection( &freetype_cs ); return ret; } @@ -2930,11 +2959,13 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) if(list_empty(&font_list)) /* No fonts installed */ { TRACE("No fonts installed\n"); + LeaveCriticalSection( &freetype_cs ); return NULL; } if(!have_installed_roman_font) { TRACE("No roman font installed\n"); + LeaveCriticalSection( &freetype_cs ); return NULL; } @@ -3096,6 +3127,7 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) if(!last_resort_family) { FIXME("can't find a single appropriate font - bailing\n"); free_font(ret); + LeaveCriticalSection( &freetype_cs ); return NULL; } @@ -3186,6 +3218,7 @@ found: if (!ret->ft_face) { free_font( ret ); + LeaveCriticalSection( &freetype_cs ); return 0; } @@ -3211,6 +3244,7 @@ found: TRACE("caching: gdiFont=%p hfont=%p\n", ret, hfont); list_add_head(&gdi_font_list, &ret->entry); + LeaveCriticalSection( &freetype_cs ); return ret; } @@ -3248,6 +3282,8 @@ BOOL WineEngDestroyFontInstance(HFONT handle) struct list *font_elem_ptr, *hfontlist_elem_ptr; int i = 0; + EnterCriticalSection( &freetype_cs ); + LIST_FOR_EACH_ENTRY(gdiFont, &child_font_list, struct tagGdiFont, entry) { struct list *first_hfont = list_head(&gdiFont->hfontlist); @@ -3256,6 +3292,7 @@ BOOL WineEngDestroyFontInstance(HFONT handle) { TRACE("removing child font %p from child list\n", gdiFont); list_remove(&gdiFont->entry); + LeaveCriticalSection( &freetype_cs ); return TRUE; } } @@ -3297,6 +3334,7 @@ BOOL WineEngDestroyFontInstance(HFONT handle) list_remove(&gdiFont->entry); free_font(gdiFont); } + LeaveCriticalSection( &freetype_cs ); return ret; } @@ -3413,7 +3451,7 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam) struct list *family_elem_ptr, *face_elem_ptr; ENUMLOGFONTEXW elf; NEWTEXTMETRICEXW ntm; - DWORD type, ret = 1; + DWORD type; FONTSIGNATURE fs; CHARSETINFO csi; LOGFONTW lf; @@ -3429,6 +3467,7 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam) TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet); + EnterCriticalSection( &freetype_cs ); if(plf->lfFaceName[0]) { FontSubst *psub; psub = get_font_subst(&font_subst_list, plf->lfFaceName, plf->lfCharSet); @@ -3476,8 +3515,10 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam) csi.ciCharset, type, debugstr_w(elf.elfScript), elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight, ntm.ntmTm.ntmFlags); - ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam); - if(!ret) goto end; + /* release section before callback (FIXME) */ + LeaveCriticalSection( &freetype_cs ); + if (!proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam)) return 0; + EnterCriticalSection( &freetype_cs ); } } } @@ -3517,13 +3558,15 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam) csi.ciCharset, type, debugstr_w(elf.elfScript), elf.elfLogFont.lfItalic, elf.elfLogFont.lfWeight, ntm.ntmTm.ntmFlags); - ret = proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam); - if(!ret) goto end; + /* release section before callback (FIXME) */ + LeaveCriticalSection( &freetype_cs ); + if (!proc(&elf.elfLogFont, (TEXTMETRICW *)&ntm, type, lparam)) return 0; + EnterCriticalSection( &freetype_cs ); } } } -end: - return ret; + LeaveCriticalSection( &freetype_cs ); + return 1; } static void FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt) @@ -3556,7 +3599,7 @@ static BOOL codepage_sets_default_used(UINT codepage) } } -static FT_UInt get_glyph_index(GdiFont *font, UINT glyph) +static FT_UInt get_glyph_index(const GdiFont *font, UINT glyph) { if(font->ft_face->charmap->encoding == FT_ENCODING_NONE) { WCHAR wc = (WCHAR)glyph; @@ -3641,6 +3684,8 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm, buflen, buf, lpmat); + EnterCriticalSection( &freetype_cs ); + if(format & GGO_GLYPH_INDEX) { glyph_index = glyph; format &= ~GGO_GLYPH_INDEX; @@ -3656,6 +3701,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, } else { if(format == GGO_METRICS && font->gm[glyph_index / GM_BLOCK_SIZE] != NULL && FONT_GM(font,glyph_index)->init ) { *lpgm = FONT_GM(font,glyph_index)->gm; + LeaveCriticalSection( &freetype_cs ); return 1; /* FIXME */ } } @@ -3670,6 +3716,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, if(err) { WARN("FT_Load_Glyph on index %x returns %d\n", glyph_index, err); + LeaveCriticalSection( &freetype_cs ); return GDI_ERROR; } @@ -3794,10 +3841,14 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, } if(format == GGO_METRICS) + { + LeaveCriticalSection( &freetype_cs ); return 1; /* FIXME */ + } if(ft_face->glyph->format != ft_glyph_format_outline && format != GGO_BITMAP && format != WINE_GGO_GRAY16_BITMAP) { TRACE("loaded a bitmap\n"); + LeaveCriticalSection( &freetype_cs ); return GDI_ERROR; } @@ -3844,6 +3895,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, default: FIXME("loaded glyph format %x\n", ft_face->glyph->format); + LeaveCriticalSection( &freetype_cs ); return GDI_ERROR; } break; @@ -3875,6 +3927,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, src += ft_face->glyph->bitmap.pitch; dst += pitch; } + LeaveCriticalSection( &freetype_cs ); return needed; } case ft_glyph_format_outline: @@ -3901,12 +3954,15 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, else if(format == GGO_GRAY8_BITMAP) mult = 64; else /* format == WINE_GGO_GRAY16_BITMAP */ + { + LeaveCriticalSection( &freetype_cs ); return needed; - + } break; } default: FIXME("loaded glyph format %x\n", ft_face->glyph->format); + LeaveCriticalSection( &freetype_cs ); return GDI_ERROR; } @@ -4103,8 +4159,10 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, default: FIXME("Unsupported format %d\n", format); + LeaveCriticalSection( &freetype_cs ); return GDI_ERROR; } + LeaveCriticalSection( &freetype_cs ); return needed; } @@ -4174,7 +4232,7 @@ static BOOL get_bitmap_text_metrics(GdiFont *font) } -static void scale_font_metrics(GdiFont *font, LPTEXTMETRICW ptm) +static void scale_font_metrics(const GdiFont *font, LPTEXTMETRICW ptm) { float scale_x; @@ -4202,15 +4260,23 @@ static void scale_font_metrics(GdiFont *font, LPTEXTMETRICW ptm) */ BOOL WineEngGetTextMetrics(GdiFont *font, LPTEXTMETRICW ptm) { + EnterCriticalSection( &freetype_cs ); if(!font->potm) { if(!WineEngGetOutlineTextMetrics(font, 0, NULL)) if(!get_bitmap_text_metrics(font)) + { + LeaveCriticalSection( &freetype_cs ); return FALSE; + } + } + if(!font->potm) + { + LeaveCriticalSection( &freetype_cs ); + return FALSE; } - if(!font->potm) return FALSE; memcpy(ptm, &font->potm->otmTextMetrics, sizeof(*ptm)); scale_font_metrics(font, ptm); - + LeaveCriticalSection( &freetype_cs ); return TRUE; } @@ -4238,12 +4304,15 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize, if(!FT_IS_SCALABLE(ft_face)) return 0; + EnterCriticalSection( &freetype_cs ); + if(font->potm) { if(cbSize >= font->potm->otmSize) { memcpy(potm, font->potm, font->potm->otmSize); scale_font_metrics(font, &potm->otmTextMetrics); } + LeaveCriticalSection( &freetype_cs ); return font->potm->otmSize; } @@ -4480,6 +4549,7 @@ end: HeapFree(GetProcessHeap(), 0, style_nameW); HeapFree(GetProcessHeap(), 0, family_nameW); + LeaveCriticalSection( &freetype_cs ); return ret; } @@ -4497,6 +4567,7 @@ static BOOL load_child_font(GdiFont *font, CHILD_FONT *child) child->font->ntmFlags = child->face->ntmFlags; child->font->orientation = font->orientation; + child->font->scale_y = font->scale_y; hfontlist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hfontlist)); hfontlist->hfont = CreateFontIndirectW(&font->font_desc.lf); list_add_head(&child->font->hfontlist, &hfontlist->entry); @@ -4552,12 +4623,14 @@ BOOL WineEngGetCharWidth(GdiFont *font, UINT firstChar, UINT lastChar, TRACE("%p, %d, %d, %p\n", font, firstChar, lastChar, buffer); + EnterCriticalSection( &freetype_cs ); for(c = firstChar; c <= lastChar; c++) { get_glyph_index_linked(font, c, &linked_font, &glyph_index); WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, NULL); buffer[c - firstChar] = FONT_GM(linked_font,glyph_index)->adv; } + LeaveCriticalSection( &freetype_cs ); return TRUE; } @@ -4578,6 +4651,8 @@ BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar, if(!FT_IS_SCALABLE(font->ft_face)) return FALSE; + EnterCriticalSection( &freetype_cs ); + for(c = firstChar; c <= lastChar; c++) { get_glyph_index_linked(font, c, &linked_font, &glyph_index); WineEngGetGlyphOutline(linked_font, glyph_index, GGO_METRICS | GGO_GLYPH_INDEX, @@ -4587,6 +4662,7 @@ BOOL WineEngGetCharABCWidths(GdiFont *font, UINT firstChar, UINT lastChar, buffer[c - firstChar].abcC = FONT_GM(linked_font,glyph_index)->adv - FONT_GM(linked_font,glyph_index)->lsb - FONT_GM(linked_font,glyph_index)->bbx; } + LeaveCriticalSection( &freetype_cs ); return TRUE; } @@ -4605,6 +4681,8 @@ BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD if(!FT_HAS_HORIZONTAL(font->ft_face)) return FALSE; + EnterCriticalSection( &freetype_cs ); + get_glyph_index_linked(font, 'a', &linked_font, &glyph_index); if (!pgi) for(c = firstChar; c < firstChar+count; c++) { @@ -4625,6 +4703,7 @@ BOOL WineEngGetCharABCWidthsI(GdiFont *font, UINT firstChar, UINT count, LPWORD - FONT_GM(linked_font,pgi[c])->lsb - FONT_GM(linked_font,pgi[c])->bbx; } + LeaveCriticalSection( &freetype_cs ); return TRUE; } @@ -4645,6 +4724,8 @@ BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count, TRACE("%p, %s, %d, %d, %p\n", font, debugstr_wn(wstr, count), count, max_ext, size); + EnterCriticalSection( &freetype_cs ); + size->cx = 0; WineEngGetTextMetrics(font, &tm); size->cy = tm.tmHeight; @@ -4665,6 +4746,7 @@ BOOL WineEngGetTextExtentExPoint(GdiFont *font, LPCWSTR wstr, INT count, if (pnfit) *pnfit = nfit; + LeaveCriticalSection( &freetype_cs ); TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit); return TRUE; } @@ -4683,6 +4765,8 @@ BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count, TRACE("%p, %p, %d, %d, %p\n", font, indices, count, max_ext, size); + EnterCriticalSection( &freetype_cs ); + size->cx = 0; WineEngGetTextMetrics(font, &tm); size->cy = tm.tmHeight; @@ -4703,6 +4787,7 @@ BOOL WineEngGetTextExtentExPointI(GdiFont *font, const WORD *indices, INT count, if (pnfit) *pnfit = nfit; + LeaveCriticalSection( &freetype_cs ); TRACE("return %d, %d, %d\n", size->cx, size->cy, nfit); return TRUE; } @@ -4779,6 +4864,7 @@ BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph) struct list *first_hfont; BOOL ret; + EnterCriticalSection( &freetype_cs ); ret = get_glyph_index_linked(font, c, &linked_font, glyph); TRACE("get_glyph_index_linked glyph %d font %p\n", *glyph, linked_font); if(font == linked_font) @@ -4788,7 +4874,7 @@ BOOL WineEngGetLinkedHFont(DC *dc, WCHAR c, HFONT *new_hfont, UINT *glyph) first_hfont = list_head(&linked_font->hfontlist); *new_hfont = LIST_ENTRY(first_hfont, struct tagHFONTLIST, entry)->hfont; } - + LeaveCriticalSection( &freetype_cs ); return ret; } @@ -4872,7 +4958,11 @@ DWORD WineEngGetFontUnicodeRanges(GdiFont *font, LPGLYPHSET glyphset) */ BOOL WineEngFontIsLinked(GdiFont *font) { - return !list_empty(&font->child_fonts); + BOOL ret; + EnterCriticalSection( &freetype_cs ); + ret = !list_empty(&font->child_fonts); + LeaveCriticalSection( &freetype_cs ); + return ret; } static BOOL is_hinting_enabled(void) @@ -5022,14 +5112,17 @@ DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair USHORT i, nTables; USHORT *glyph_to_char; + EnterCriticalSection( &freetype_cs ); if (font->total_kern_pairs != (DWORD)-1) { if (cPairs && kern_pair) { cPairs = min(cPairs, font->total_kern_pairs); memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair)); + LeaveCriticalSection( &freetype_cs ); return cPairs; } + LeaveCriticalSection( &freetype_cs ); return font->total_kern_pairs; } @@ -5040,6 +5133,7 @@ DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair if (length == GDI_ERROR) { TRACE("no kerning data in the font\n"); + LeaveCriticalSection( &freetype_cs ); return 0; } @@ -5047,6 +5141,7 @@ DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair if (!buf) { WARN("Out of memory\n"); + LeaveCriticalSection( &freetype_cs ); return 0; } @@ -5058,6 +5153,7 @@ DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair { WARN("Out of memory allocating a glyph index to char code map\n"); HeapFree(GetProcessHeap(), 0, buf); + LeaveCriticalSection( &freetype_cs ); return 0; } @@ -5148,8 +5244,10 @@ DWORD WineEngGetKerningPairs(GdiFont *font, DWORD cPairs, KERNINGPAIR *kern_pair { cPairs = min(cPairs, font->total_kern_pairs); memcpy(kern_pair, font->kern_pairs, cPairs * sizeof(*kern_pair)); + LeaveCriticalSection( &freetype_cs ); return cPairs; } + LeaveCriticalSection( &freetype_cs ); return font->total_kern_pairs; } diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec index 2e79346d634..1a41c2013fc 100644 --- a/dlls/gdi32/gdi32.spec +++ b/dlls/gdi32/gdi32.spec @@ -189,9 +189,9 @@ # @ stub GdiGetPageCount # @ stub GdiGetPageHandle # @ stub GdiGetSpoolFileHandle -# @ stub GdiGetSpoolMessage +@ stdcall GdiGetSpoolMessage(ptr long ptr long) @ stdcall GdiGradientFill(long ptr long ptr long long) -# @ stub GdiInitSpool +@ stdcall GdiInitSpool() # @ stub GdiInitializeLanguagePack @ stdcall GdiIsMetaFileDC(long) @ stdcall GdiIsMetaPrintDC(long) diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 21cf577992b..51932b065fd 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -397,9 +397,6 @@ extern void CLIPPING_UpdateGCRegion( DC * dc ) DECLSPEC_HIDDEN; /* dc.c */ extern DC *alloc_dc_ptr( const DC_FUNCTIONS *funcs, WORD magic ) DECLSPEC_HIDDEN; -extern DC * DC_GetDCUpdate( HDC hdc ) DECLSPEC_HIDDEN; -extern DC * DC_GetDCPtr( HDC hdc ) DECLSPEC_HIDDEN; -extern void DC_ReleaseDCPtr( DC *dc ) DECLSPEC_HIDDEN; extern BOOL free_dc_ptr( DC *dc ) DECLSPEC_HIDDEN; extern DC *get_dc_ptr( HDC hdc ) DECLSPEC_HIDDEN; extern void release_dc_ptr( DC *dc ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c index 91cfb71539c..e2c9533f526 100644 --- a/dlls/gdi32/gdiobj.c +++ b/dlls/gdi32/gdiobj.c @@ -823,7 +823,7 @@ BOOL WINAPI DeleteObject( HGDIOBJ obj ) while (header->hdcs) { - DC *dc = DC_GetDCPtr(header->hdcs->hdc); + DC *dc = get_dc_ptr(header->hdcs->hdc); struct hdc_list *tmp; TRACE("hdc %p has interest in %p\n", header->hdcs->hdc, obj); @@ -831,7 +831,7 @@ BOOL WINAPI DeleteObject( HGDIOBJ obj ) { if(dc->funcs->pDeleteObject) dc->funcs->pDeleteObject( dc->physDev, obj ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); } tmp = header->hdcs; header->hdcs = header->hdcs->next; @@ -1098,10 +1098,10 @@ DWORD WINAPI GetObjectType( HGDIOBJ handle ) HGDIOBJ WINAPI GetCurrentObject(HDC hdc,UINT type) { HGDIOBJ ret = 0; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); + + if (!dc) return 0; - if (dc) - { switch (type) { case OBJ_EXTPEN: /* fall through */ case OBJ_PEN: ret = dc->hPen; break; @@ -1112,13 +1112,12 @@ HGDIOBJ WINAPI GetCurrentObject(HDC hdc,UINT type) /* tests show that OBJ_REGION is explicitly ignored */ case OBJ_REGION: break; - default: - /* the SDK only mentions those above */ - FIXME("(%p,%d): unknown type.\n",hdc,type); + default: + /* the SDK only mentions those above */ + FIXME("(%p,%d): unknown type.\n",hdc,type); break; - } - DC_ReleaseDCPtr( dc ); } + release_dc_ptr( dc ); return ret; } @@ -1143,23 +1142,15 @@ HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ hObj ) { HGDIOBJ ret = 0; GDIOBJHDR *header; - DC *dc; TRACE( "(%p,%p)\n", hdc, hObj ); - if (!(dc = DC_GetDCPtr( hdc ))) - SetLastError( ERROR_INVALID_HANDLE ); - else + header = GDI_GetObjPtr( hObj, MAGIC_DONTCARE ); + if (header) { - DC_ReleaseDCPtr( dc ); - - header = GDI_GetObjPtr( hObj, MAGIC_DONTCARE ); - if (header) - { - const struct gdi_obj_funcs *funcs = header->funcs; - GDI_ReleaseObj( hObj ); - if (funcs && funcs->pSelectObject) ret = funcs->pSelectObject( hObj, hdc ); - } + const struct gdi_obj_funcs *funcs = header->funcs; + GDI_ReleaseObj( hObj ); + if (funcs && funcs->pSelectObject) ret = funcs->pSelectObject( hObj, hdc ); } return ret; } @@ -1437,13 +1428,13 @@ BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca) */ BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData) { - DC *dc = DC_GetDCPtr(hdc); + DC *dc = get_dc_ptr(hdc); BOOL ret = FALSE; if(dc) { if (dc->funcs->pGdiComment) ret = dc->funcs->pGdiComment( dc->physDev, cbSize, lpData ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); } return ret; } diff --git a/dlls/gdi32/palette.c b/dlls/gdi32/palette.c index 54d2d067d04..b55a6f822a7 100644 --- a/dlls/gdi32/palette.c +++ b/dlls/gdi32/palette.c @@ -515,11 +515,11 @@ UINT WINAPI GetSystemPaletteEntries( TRACE("hdc=%p,start=%i,count=%i\n", hdc,start,count); - if ((dc = DC_GetDCPtr( hdc ))) + if ((dc = get_dc_ptr( hdc ))) { if (dc->funcs->pGetSystemPaletteEntries) ret = dc->funcs->pGetSystemPaletteEntries( dc->physDev, start, count, entries ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); } return ret; } @@ -584,18 +584,18 @@ COLORREF WINAPI GetNearestColor( COLORREF nearest; DC *dc; - if (!(dc = DC_GetDCPtr( hdc ))) return CLR_INVALID; + if (!(dc = get_dc_ptr( hdc ))) return CLR_INVALID; if (dc->funcs->pGetNearestColor) { nearest = dc->funcs->pGetNearestColor( dc->physDev, color ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return nearest; } if (!(GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)) { - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return color; } @@ -618,14 +618,14 @@ COLORREF WINAPI GetNearestColor( WARN("RGB(%x) : idx %d is out of bounds, assuming NULL\n", color, index ); if (!GetPaletteEntries( hpal, 0, 1, &entry )) { - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return CLR_INVALID; } } color = RGB( entry.peRed, entry.peGreen, entry.peBlue ); } nearest = color & 0x00ffffff; - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); TRACE("(%06x): returning %06x\n", color, nearest ); return nearest; @@ -662,11 +662,9 @@ static BOOL PALETTE_UnrealizeObject( HGDIOBJ handle, void *obj ) palette->funcs = NULL; } - if (hLastRealizedPalette == handle) - { + if (InterlockedCompareExchangePointer( (void **)&hLastRealizedPalette, 0, handle ) == handle) TRACE("unrealizing palette %p\n", handle); - hLastRealizedPalette = 0; - } + return TRUE; } @@ -696,7 +694,7 @@ HPALETTE WINAPI GDISelectPalette( HDC hdc, HPALETTE hpal, WORD wBkg) WARN("invalid selected palette %p\n",hpal); return 0; } - if (!(dc = DC_GetDCPtr( hdc ))) return 0; + if (!(dc = get_dc_ptr( hdc ))) return 0; ret = dc->hPalette; if (dc->funcs->pSelectPalette) hpal = dc->funcs->pSelectPalette( dc->physDev, hpal, FALSE ); if (hpal) @@ -705,7 +703,7 @@ HPALETTE WINAPI GDISelectPalette( HDC hdc, HPALETTE hpal, WORD wBkg) if (!wBkg) hPrimaryPalette = hpal; } else ret = 0; - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -716,7 +714,7 @@ HPALETTE WINAPI GDISelectPalette( HDC hdc, HPALETTE hpal, WORD wBkg) UINT WINAPI GDIRealizePalette( HDC hdc ) { UINT realized = 0; - DC* dc = DC_GetDCPtr( hdc ); + DC* dc = get_dc_ptr( hdc ); if (!dc) return 0; @@ -727,7 +725,7 @@ UINT WINAPI GDIRealizePalette( HDC hdc ) if (dc->funcs->pRealizeDefaultPalette) realized = dc->funcs->pRealizeDefaultPalette( dc->physDev ); } - else if(dc->hPalette != hLastRealizedPalette ) + else if (InterlockedExchangePointer( (void **)&hLastRealizedPalette, dc->hPalette ) != dc->hPalette) { if (dc->funcs->pRealizePalette) { @@ -740,11 +738,10 @@ UINT WINAPI GDIRealizePalette( HDC hdc ) GDI_ReleaseObj( dc->hPalette ); } } - hLastRealizedPalette = dc->hPalette; } else TRACE(" skipping (hLastRealizedPalette = %p)\n", hLastRealizedPalette); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); TRACE(" realized %i colors.\n", realized ); return realized; } @@ -760,10 +757,10 @@ UINT16 WINAPI RealizeDefaultPalette16( HDC16 hdc ) TRACE("%04x\n", hdc ); - if (!(dc = DC_GetDCPtr( HDC_32(hdc) ))) return 0; + if (!(dc = get_dc_ptr( HDC_32(hdc) ))) return 0; if (dc->funcs->pRealizeDefaultPalette) ret = dc->funcs->pRealizeDefaultPalette( dc->physDev ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -772,11 +769,11 @@ UINT16 WINAPI RealizeDefaultPalette16( HDC16 hdc ) */ BOOL16 WINAPI IsDCCurrentPalette16(HDC16 hDC) { - DC *dc = DC_GetDCPtr( HDC_32(hDC) ); + DC *dc = get_dc_ptr( HDC_32(hDC) ); if (dc) { BOOL bRet = dc->hPalette == hPrimaryPalette; - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return bRet; } return FALSE; diff --git a/dlls/gdi32/pen.c b/dlls/gdi32/pen.c index 5647d7e58a5..971dadd5a20 100644 --- a/dlls/gdi32/pen.c +++ b/dlls/gdi32/pen.c @@ -218,19 +218,31 @@ HPEN WINAPI ExtCreatePen( DWORD style, DWORD width, static HGDIOBJ PEN_SelectObject( HGDIOBJ handle, HDC hdc ) { HGDIOBJ ret = 0; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); - if (!dc) return 0; + if (!dc) + { + SetLastError( ERROR_INVALID_HANDLE ); + return 0; + } + + if (!GDI_inc_ref_count( handle )) + { + release_dc_ptr( dc ); + return 0; + } - if (dc->funcs->pSelectPen) handle = dc->funcs->pSelectPen( dc->physDev, handle ); - if (handle) + if (dc->funcs->pSelectPen && !dc->funcs->pSelectPen( dc->physDev, handle )) + { + GDI_dec_ref_count( handle ); + } + else { ret = dc->hPen; dc->hPen = handle; - GDI_inc_ref_count( handle ); GDI_dec_ref_count( ret ); } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } diff --git a/dlls/gdi32/printdrv.c b/dlls/gdi32/printdrv.c index 5bfabb9dc7b..8524388100d 100644 --- a/dlls/gdi32/printdrv.c +++ b/dlls/gdi32/printdrv.c @@ -57,6 +57,28 @@ static const char DefaultDevMode[] = "Default DevMode"; static const char PrinterDriverData[] = "PrinterDriverData"; static const char Printers[] = "System\\CurrentControlSet\\Control\\Print\\Printers\\"; +/****************************************************************** + * GdiGetSpoolMessage [GDI32.@] + * + */ +DWORD WINAPI GdiGetSpoolMessage(LPVOID ptr1, DWORD data2, LPVOID ptr3, DWORD data4) +{ + TRACE("(%p 0x%x %p 0x%x) stub\n", ptr1, data2, ptr3, data4); + /* avoid 100% cpu usage with spoolsv.exe from w2k + (spoolsv.exe from xp does Sleep 1000/1500/2000 in a loop) */ + Sleep(500); + return 0; +} + +/****************************************************************** + * GdiInitSpool [GDI32.@] + * + */ +DWORD WINAPI GdiInitSpool(void) +{ + FIXME("stub\n"); + return TRUE; +} /****************************************************************** * StartDocA [GDI32.@] diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c index 573fe56b744..c31d367b0d9 100644 --- a/dlls/gdi32/tests/bitmap.c +++ b/dlls/gdi32/tests/bitmap.c @@ -1699,12 +1699,12 @@ static void test_mono_1x1_bmp_dbg(HBITMAP hbmp, int line) ok_(__FILE__, line)(ret == sizeof(BITMAP) || ret == sizeof(DIBSECTION) /* Win9x, only for curObj2 */, "GetObject returned %d, error %u\n", ret, GetLastError()); - ok_(__FILE__, line)(bm.bmType == 0, "wrong bmType %d\n", bm.bmType); - ok_(__FILE__, line)(bm.bmWidth == 1, "wrong bmWidth %d\n", bm.bmWidth); - ok_(__FILE__, line)(bm.bmHeight == 1, "wrong bmHeight %d\n", bm.bmHeight); - ok_(__FILE__, line)(bm.bmWidthBytes == 2, "wrong bmWidthBytes %d\n", bm.bmWidthBytes); - ok_(__FILE__, line)(bm.bmPlanes == 1, "wrong bmPlanes %u\n", bm.bmPlanes); - ok_(__FILE__, line)(bm.bmBitsPixel == 1, "wrong bmBitsPixel %d\n", bm.bmBitsPixel); + ok_(__FILE__, line)(bm.bmType == 0, "wrong bmType, expected 0 got %d\n", bm.bmType); + ok_(__FILE__, line)(bm.bmWidth == 1, "wrong bmWidth, expected 1 got %d\n", bm.bmWidth); + ok_(__FILE__, line)(bm.bmHeight == 1, "wrong bmHeight, expected 1 got %d\n", bm.bmHeight); + ok_(__FILE__, line)(bm.bmWidthBytes == 2, "wrong bmWidthBytes, expected 2 got %d\n", bm.bmWidthBytes); + ok_(__FILE__, line)(bm.bmPlanes == 1, "wrong bmPlanes, expected 1 got %u\n", bm.bmPlanes); + ok_(__FILE__, line)(bm.bmBitsPixel == 1, "wrong bmBitsPixel, expected 1 got %d\n", bm.bmBitsPixel); ok_(__FILE__, line)(!bm.bmBits, "wrong bmBits %p\n", bm.bmBits); } diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec index 1b9e427a8fe..33b474de088 100644 --- a/dlls/gdiplus/gdiplus.spec +++ b/dlls/gdiplus/gdiplus.spec @@ -575,7 +575,7 @@ @ stdcall GdipSetPenLineCap197819(ptr long long long) @ stdcall GdipSetPenLineJoin(ptr long) @ stdcall GdipSetPenMiterLimit(ptr long) -@ stub GdipSetPenMode +@ stdcall GdipSetPenMode(ptr long) @ stdcall GdipSetPenStartCap(ptr long) @ stub GdipSetPenTransform @ stub GdipSetPenUnit @@ -587,7 +587,7 @@ @ stdcall GdipSetSolidFillColor(ptr ptr) @ stdcall GdipSetStringFormatAlign(ptr long) @ stub GdipSetStringFormatDigitSubstitution -@ stub GdipSetStringFormatFlags +@ stdcall GdipSetStringFormatFlags(ptr long) @ stdcall GdipSetStringFormatHotkeyPrefix(ptr long) @ stdcall GdipSetStringFormatLineAlign(ptr long) @ stub GdipSetStringFormatMeasurableCharacterRanges diff --git a/dlls/gdiplus/pen.c b/dlls/gdiplus/pen.c index 92d76d834c7..97fc99dacdf 100644 --- a/dlls/gdiplus/pen.c +++ b/dlls/gdiplus/pen.c @@ -380,3 +380,13 @@ GpStatus WINGDIPAPI GdipSetPenWidth(GpPen *pen, REAL width) return Ok; } + + +GpStatus WINGDIPAPI GdipSetPenMode(GpPen *pen, GpPenAlignment penAlignment) +{ + if(!pen) return InvalidParameter; + + FIXME("stub (%d)\n", penAlignment); + + return Ok; +} diff --git a/dlls/gdiplus/stringformat.c b/dlls/gdiplus/stringformat.c index e328ffb249b..7de1c2cbf9e 100644 --- a/dlls/gdiplus/stringformat.c +++ b/dlls/gdiplus/stringformat.c @@ -28,6 +28,9 @@ #include "gdiplus.h" #include "gdiplus_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(gdiplus); GpStatus WINGDIPAPI GdipCreateStringFormat(INT attr, LANGID lang, GpStringFormat **format) @@ -142,3 +145,10 @@ GpStatus WINGDIPAPI GdipSetStringFormatTrimming(GpStringFormat *format, return Ok; } + +GpStatus WINGDIPAPI GdipSetStringFormatFlags(GDIPCONST GpStringFormat *format, INT flags) +{ + FIXME("format (%p) flags (%d)\n", format, flags); + + return Ok; +} diff --git a/dlls/gdiplus/tests/graphicspath.c b/dlls/gdiplus/tests/graphicspath.c index b2d5ef9912c..3860a2ece4a 100644 --- a/dlls/gdiplus/tests/graphicspath.c +++ b/dlls/gdiplus/tests/graphicspath.c @@ -224,7 +224,7 @@ static path_test_t arc_path[] = { {187.9, 716.5, PathPointTypeBezier, 0, 0}, /*34*/ {293.1, 841.8, PathPointTypeBezier, 0, 0}, /*35*/ {450.9, 824.1, PathPointTypeBezier, 0, 0}, /*36*/ - {540.4, 676.9, PathPointTypeBezier, 0, 0} /*37*/ + {540.4, 676.9, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 1} /*37*/ }; static void test_arc(void) diff --git a/dlls/hlink/extserv.c b/dlls/hlink/extserv.c index c7a1b779d0f..daedf9eac74 100644 --- a/dlls/hlink/extserv.c +++ b/dlls/hlink/extserv.c @@ -63,7 +63,7 @@ static HRESULT WINAPI ExtServUnk_QueryInterface(IUnknown *iface, REFIID riid, vo } if(*ppv) { - IUnknown_AddRef(EXTSERVUNK(This)); + IUnknown_AddRef((IUnknown*)*ppv); return S_OK; } @@ -209,6 +209,9 @@ static const IHttpNegotiateVtbl HttpNegotiateVtbl = { HttpNegotiate_OnResponse }; +/*********************************************************************** + * HlinkCreateExtensionServices (HLINK.@) + */ HRESULT WINAPI HlinkCreateExtensionServices(LPCWSTR pwzAdditionalHeaders, HWND phwnd, LPCWSTR pszUsername, LPCWSTR pszPassword, IUnknown *punkOuter, REFIID riid, void** ppv) diff --git a/dlls/hlink/hlink.spec b/dlls/hlink/hlink.spec index 7dac4d90e5c..0cc761fbcb6 100644 --- a/dlls/hlink/hlink.spec +++ b/dlls/hlink/hlink.spec @@ -8,10 +8,10 @@ 10 stdcall HlinkNavigate(ptr ptr long ptr ptr ptr) 11 stdcall HlinkUpdateStackItem(ptr ptr long ptr wstr wstr) 12 stub HlinkOnRenameDocument -14 stub HlinkResolveMonikerForData +14 stdcall HlinkResolveMonikerForData(ptr long ptr long ptr ptr ptr) 15 stub HlinkResolveStringForData 16 stub OleSaveToStreamEx -18 stub HlinkParseDisplayName +18 stdcall HlinkParseDisplayName(ptr wstr long ptr ptr) 20 stdcall HlinkQueryCreateFromData(ptr) 21 stub HlinkSetSpecialReference 22 stdcall HlinkGetSpecialReference(long ptr) diff --git a/dlls/hlink/hlink_main.c b/dlls/hlink/hlink_main.c index 4e321899c39..43e9e7f3b3d 100644 --- a/dlls/hlink/hlink_main.c +++ b/dlls/hlink/hlink_main.c @@ -41,8 +41,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) switch (fdwReason) { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL); break; @@ -52,12 +50,18 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return TRUE; } +/*********************************************************************** + * DllCanUnloadNow (HLINK.@) + */ HRESULT WINAPI DllCanUnloadNow( void ) { FIXME("\n"); return S_OK; } +/*********************************************************************** + * HlinkCreateFromMoniker (HLINK.@) + */ HRESULT WINAPI HlinkCreateFromMoniker( IMoniker *pimkTrgt, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName, IHlinkSite* pihlsite, DWORD dwSiteData, IUnknown* piunkOuter, REFIID riid, void** ppvObj) @@ -89,6 +93,9 @@ HRESULT WINAPI HlinkCreateFromMoniker( IMoniker *pimkTrgt, LPCWSTR pwzLocation, return r; } +/*********************************************************************** + * HlinkCreateFromString (HLINK.@) + */ HRESULT WINAPI HlinkCreateFromString( LPCWSTR pwzTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName, IHlinkSite* pihlsite, DWORD dwSiteData, IUnknown* piunkOuter, REFIID riid, void** ppvObj) @@ -151,6 +158,9 @@ HRESULT WINAPI HlinkCreateFromString( LPCWSTR pwzTarget, LPCWSTR pwzLocation, } +/*********************************************************************** + * HlinkNavigate (HLINK.@) + */ HRESULT WINAPI HlinkCreateBrowseContext( IUnknown* piunkOuter, REFIID riid, void** ppvObj) { HRESULT r = S_OK; @@ -164,6 +174,9 @@ HRESULT WINAPI HlinkCreateBrowseContext( IUnknown* piunkOuter, REFIID riid, void return r; } +/*********************************************************************** + * HlinkNavigate (HLINK.@) + */ HRESULT WINAPI HlinkNavigate(IHlink *phl, IHlinkFrame *phlFrame, DWORD grfHLNF, LPBC pbc, IBindStatusCallback *pbsc, IHlinkBrowseContext *phlbc) @@ -180,6 +193,9 @@ HRESULT WINAPI HlinkNavigate(IHlink *phl, IHlinkFrame *phlFrame, return r; } +/*********************************************************************** + * HlinkOnNavigate (HLINK.@) + */ HRESULT WINAPI HlinkOnNavigate( IHlinkFrame *phlFrame, IHlinkBrowseContext* phlbc, DWORD grfHLNF, IMoniker *pmkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName, ULONG* puHLID) @@ -199,6 +215,9 @@ HRESULT WINAPI HlinkOnNavigate( IHlinkFrame *phlFrame, return r; } +/*********************************************************************** + * HlinkCreateFromData (HLINK.@) + */ HRESULT WINAPI HlinkCreateFromData(IDataObject *piDataObj, IHlinkSite *pihlsite, DWORD dwSiteData, IUnknown *piunkOuter, REFIID riid, void **ppvObj) @@ -209,12 +228,18 @@ HRESULT WINAPI HlinkCreateFromData(IDataObject *piDataObj, return E_NOTIMPL; } +/*********************************************************************** + * HlinkQueryCreateFromData (HLINK.@) + */ HRESULT WINAPI HlinkQueryCreateFromData(IDataObject* piDataObj) { FIXME("%p\n", piDataObj); return E_NOTIMPL; } +/*********************************************************************** + * HlinkNavigateToStringReference (HLINK.@) + */ HRESULT WINAPI HlinkNavigateToStringReference( LPCWSTR pwzTarget, LPCWSTR pwzLocation, IHlinkSite *pihlsite, DWORD dwSiteData, IHlinkFrame *pihlframe, DWORD grfHLNF, LPBC pibc, @@ -235,6 +260,9 @@ HRESULT WINAPI HlinkNavigateToStringReference( LPCWSTR pwzTarget, return r; } +/*********************************************************************** + * HlinkIsShortcut (HLINK.@) + */ HRESULT WINAPI HlinkIsShortcut(LPCWSTR pwzFileName) { int len; @@ -253,6 +281,9 @@ HRESULT WINAPI HlinkIsShortcut(LPCWSTR pwzFileName) return strcmpiW(pwzFileName+len, url_ext) ? S_FALSE : S_OK; } +/*********************************************************************** + * HlinkGetSpecialReference (HLINK.@) + */ HRESULT WINAPI HlinkGetSpecialReference(ULONG uReference, LPWSTR *ppwzReference) { DWORD res, type, size = 100; @@ -308,12 +339,18 @@ HRESULT WINAPI HlinkGetSpecialReference(ULONG uReference, LPWSTR *ppwzReference) return S_OK; } +/*********************************************************************** + * HlinkTranslateURL (HLINK.@) + */ HRESULT WINAPI HlinkTranslateURL(LPCWSTR pwzURL, DWORD grfFlags, LPWSTR *ppwzTranslatedURL) { FIXME("(%s %08x %p)\n", debugstr_w(pwzURL), grfFlags, ppwzTranslatedURL); return E_NOTIMPL; } +/*********************************************************************** + * HlinkUpdateStackItem (HLINK.@) + */ HRESULT WINAPI HlinkUpdateStackItem(IHlinkFrame *pihlframe, IHlinkBrowseContext *pihlbc, ULONG uHLID, IMoniker *pimkTrgt, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName) { @@ -322,6 +359,71 @@ HRESULT WINAPI HlinkUpdateStackItem(IHlinkFrame *pihlframe, IHlinkBrowseContext return E_NOTIMPL; } +/*********************************************************************** + * HlinkParseDisplayName (HLINK.@) + */ +HRESULT WINAPI HlinkParseDisplayName(LPBC pibc, LPCWSTR pwzDisplayName, BOOL fNoForceAbs, + ULONG *pcchEaten, IMoniker **ppimk) +{ + HRESULT hres; + + TRACE("(%p %s %x %p %p)\n", pibc, debugstr_w(pwzDisplayName), fNoForceAbs, pcchEaten, ppimk); + + if(fNoForceAbs) + FIXME("Unsupported fNoForceAbs\n"); + + hres = MkParseDisplayNameEx(pibc, pwzDisplayName, pcchEaten, ppimk); + if(SUCCEEDED(hres)) + return hres; + + hres = MkParseDisplayName(pibc, pwzDisplayName, pcchEaten, ppimk); + if(SUCCEEDED(hres)) + return hres; + + hres = CreateFileMoniker(pwzDisplayName, ppimk); + if(SUCCEEDED(hres)) + *pcchEaten = strlenW(pwzDisplayName); + + return hres; +} + +/*********************************************************************** + * HlinkResolveMonikerForData (HLINK.@) + */ +HRESULT WINAPI HlinkResolveMonikerForData(LPMONIKER pimkReference, DWORD reserved, LPBC pibc, + ULONG cFmtetc, FORMATETC *rgFmtetc, IBindStatusCallback *pibsc, LPMONIKER pimkBase) +{ + LPOLESTR name = NULL; + IBindCtx *bctx; + DWORD mksys = 0; + void *obj = NULL; + HRESULT hres; + + TRACE("(%p %x %p %d %p %p %p)\n", pimkReference, reserved, pibc, cFmtetc, rgFmtetc, pibsc, pimkBase); + + if(cFmtetc || rgFmtetc || pimkBase) + FIXME("Unsupported args\n"); + + hres = RegisterBindStatusCallback(pibc, pibsc, NULL /* FIXME */, 0); + if(FAILED(hres)) + return hres; + + hres = IMoniker_IsSystemMoniker(pimkReference, &mksys); + if(SUCCEEDED(hres) && mksys != MKSYS_URLMONIKER) + WARN("sysmk = %x\n", mksys); + + /* FIXME: What is it for? */ + CreateBindCtx(0, &bctx); + hres = IMoniker_GetDisplayName(pimkReference, bctx, NULL, &name); + IBindCtx_Release(bctx); + if(SUCCEEDED(hres)) { + TRACE("got display name %s\n", debugstr_w(name)); + CoTaskMemFree(name); + } + + return IMoniker_BindToStorage(pimkReference, pibc, NULL, &IID_IUnknown, &obj); +} + static HRESULT WINAPI HLinkCF_fnQueryInterface ( LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj) { @@ -435,6 +537,9 @@ static HRESULT register_clsid(LPCGUID guid) return S_OK; } +/*********************************************************************** + * DllRegisterServer (HLINK.@) + */ HRESULT WINAPI DllRegisterServer(void) { HRESULT r; diff --git a/dlls/hlink/tests/hlink.c b/dlls/hlink/tests/hlink.c index 271f584741c..6c3dff0591a 100644 --- a/dlls/hlink/tests/hlink.c +++ b/dlls/hlink/tests/hlink.c @@ -2,7 +2,7 @@ * Implementation of hyperlinking (hlink.dll) * * Copyright 2006 Mike McCormack - * Copyright 2007 Jacek Caban for CodeWeavers + * Copyright 2007-2008 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 @@ -28,6 +28,34 @@ #include "wine/test.h" +#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_EXPECT2(func) \ + do { \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +DEFINE_EXPECT(IsSystemMoniker); +DEFINE_EXPECT(BindToStorage); +DEFINE_EXPECT(GetDisplayName); + static const char *debugstr_w(LPCWSTR str) { static char buf[1024]; @@ -37,6 +65,18 @@ static const char *debugstr_w(LPCWSTR str) return buf; } +static const char *debugstr_guid(REFIID riid) +{ + static char buf[50]; + + sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + riid->Data1, riid->Data2, riid->Data3, riid->Data4[0], + riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4], + riid->Data4[5], riid->Data4[6], riid->Data4[7]); + + return buf; +} + static void test_HlinkIsShortcut(void) { int i; @@ -292,7 +332,7 @@ static void test_persist(void) hr = HlinkCreateFromString(url, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (LPVOID*) &lnk); - ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr); + ok(hr == S_OK, "IHlinkCreateFromString failed with error 0x%08x\n", hr); if (!lnk) { skip("Can't create lnk, skipping test_persist. Was wineprefixcreate run properly?\n"); return; @@ -448,6 +488,422 @@ static void test_HlinkCreateExtensionServices(void) IAuthenticate_Release(authenticate); } +static void test_HlinkParseDisplayName(void) +{ + IMoniker *mon = NULL; + LPWSTR name; + DWORD issys; + ULONG eaten = 0; + IBindCtx *bctx; + HRESULT hres; + + static const WCHAR winehq_urlW[] = + {'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 invalid_urlW[] = {'t','e','s','t',':','1','2','3','a','b','c',0}; + static const WCHAR clsid_nameW[] = {'c','l','s','i','d',':', + '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8', + '-','0','8','0','0','2','B','3','0','3','0','9','D',':',0}; + + CreateBindCtx(0, &bctx); + + hres = HlinkParseDisplayName(bctx, winehq_urlW, FALSE, &eaten, &mon); + ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres); + ok(eaten == sizeof(winehq_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten); + ok(mon != NULL, "mon == NULL\n"); + + hres = IMoniker_GetDisplayName(mon, bctx, 0, &name); + ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres); + ok(!lstrcmpW(name, winehq_urlW), "wrong display name %s\n", debugstr_w(name)); + CoTaskMemFree(name); + + hres = IMoniker_IsSystemMoniker(mon, &issys); + ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres); + ok(issys == MKSYS_URLMONIKER, "issys=%x\n", issys); + + IMoniker_Release(mon); + + hres = HlinkParseDisplayName(bctx, clsid_nameW, FALSE, &eaten, &mon); + ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres); + ok(eaten == sizeof(clsid_nameW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten); + ok(mon != NULL, "mon == NULL\n"); + + hres = IMoniker_IsSystemMoniker(mon, &issys); + ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres); + ok(issys == MKSYS_CLASSMONIKER, "issys=%x\n", issys); + + IMoniker_Release(mon); + + hres = HlinkParseDisplayName(bctx, invalid_urlW, FALSE, &eaten, &mon); + ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres); + ok(eaten == sizeof(invalid_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten); + ok(mon != NULL, "mon == NULL\n"); + + hres = IMoniker_GetDisplayName(mon, bctx, 0, &name); + ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres); + ok(!lstrcmpW(name, invalid_urlW), "wrong display name %s\n", debugstr_w(name)); + CoTaskMemFree(name); + + hres = IMoniker_IsSystemMoniker(mon, &issys); + ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres); + ok(issys == MKSYS_FILEMONIKER, "issys=%x\n", issys); + + IBindCtx_Release(bctx); +} + +static IBindCtx *_bctx; + +static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv) +{ + ok(0, "unexpected call\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface) +{ + return 2; +} + +static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface) +{ + return 1; +} + +static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, + REFGUID guidService, REFIID riid, void **ppv) +{ + ok(0, "unexpected service %s\n", debugstr_guid(guidService)); + return E_NOINTERFACE; +} + +static IServiceProviderVtbl ServiceProviderVtbl = { + ServiceProvider_QueryInterface, + ServiceProvider_AddRef, + ServiceProvider_Release, + ServiceProvider_QueryService +}; + +static IServiceProvider ServiceProvider = { &ServiceProviderVtbl }; + +static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + if(IsEqualGUID(riid, &IID_IServiceProvider)) { + *ppv = &ServiceProvider; + return S_OK; + } + + ok(0, "unexpected interface %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface) +{ + return 2; +} + +static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface) +{ + return 1; +} + +static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved, + IBinding *pib) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, + ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF, + DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static IBindStatusCallbackVtbl BindStatusCallbackVtbl = { + BindStatusCallback_QueryInterface, + BindStatusCallback_AddRef, + BindStatusCallback_Release, + BindStatusCallback_OnStartBinding, + BindStatusCallback_GetPriority, + BindStatusCallback_OnLowResource, + BindStatusCallback_OnProgress, + BindStatusCallback_OnStopBinding, + BindStatusCallback_GetBindInfo, + BindStatusCallback_OnDataAvailable, + BindStatusCallback_OnObjectAvailable +}; + +static IBindStatusCallback BindStatusCallback = { &BindStatusCallbackVtbl }; + +static HRESULT WINAPI Moniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv) +{ + *ppv = NULL; + + ok(0, "unexpected riid: %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI Moniker_AddRef(IMoniker *iface) +{ + return 2; +} + +static ULONG WINAPI Moniker_Release(IMoniker *iface) +{ + return 1; +} + +static HRESULT WINAPI Moniker_GetClassID(IMoniker *iface, CLSID *pClassID) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_IsDirty(IMoniker *iface) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_Load(IMoniker *iface, IStream *pStm) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_Save(IMoniker *iface, IStream *pStm, BOOL fClearDirty) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSize) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pcb, IMoniker *pmkToLeft, + REFIID riidResult, void **ppvResult) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, + REFIID riid, void **ppv) +{ + IUnknown *unk; + HRESULT hres; + + static OLECHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 }; + + CHECK_EXPECT(BindToStorage); + + ok(pbc == _bctx, "pbc != _bctx\n"); + ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft); + ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid)); + ok(ppv != NULL, "ppv == NULL\n"); + ok(*ppv == NULL, "*ppv=%p\n", *ppv); + + hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk); + ok(hres == S_OK, "GetObjectParam failed: %08x\n", hres); + ok(unk != NULL, "unk == NULL\n"); + + IUnknown_Release(unk); + + return S_OK; +} + +static HRESULT WINAPI Moniker_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar, + IMoniker **ppmkToLeft, IMoniker **ppmkReduced) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight, + BOOL fOnlyIfNotGeneric, IMoniker **ppnkComposite) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForwrd, IEnumMoniker **ppenumMoniker) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_Hash(IMoniker *iface, DWORD *pdwHash) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, + IMoniker *pmkNewlyRunning) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc, + IMoniker *pmkToLeft, FILETIME *pFileTime) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_Inverse(IMoniker *iface, IMoniker **ppmk) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther, + IMoniker **ppmkPrefix) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_RelativePathTo(IMoniker *iface, IMoniker *pmkOther, + IMoniker **pmkRelPath) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc, + IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName) +{ + static const WCHAR winehq_urlW[] = + {'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}; + + CHECK_EXPECT(GetDisplayName); + + ok(pbc != NULL, "pbc == NULL\n"); + ok(pbc != _bctx, "pbc == _bctx\n"); + ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft); + + *ppszDisplayName = CoTaskMemAlloc(sizeof(winehq_urlW)); + memcpy(*ppszDisplayName, winehq_urlW, sizeof(winehq_urlW)); + return S_OK; +} + +static HRESULT WINAPI Moniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, + IMoniker *pmkToLeft, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI Moniker_IsSystemMoniker(IMoniker *iface, DWORD *pdwMksys) +{ + CHECK_EXPECT2(IsSystemMoniker); + + *pdwMksys = MKSYS_URLMONIKER; + return S_OK; +} + +static IMonikerVtbl MonikerVtbl = { + Moniker_QueryInterface, + Moniker_AddRef, + Moniker_Release, + Moniker_GetClassID, + Moniker_IsDirty, + Moniker_Load, + Moniker_Save, + Moniker_GetSizeMax, + Moniker_BindToObject, + Moniker_BindToStorage, + Moniker_Reduce, + Moniker_ComposeWith, + Moniker_Enum, + Moniker_IsEqual, + Moniker_Hash, + Moniker_IsRunning, + Moniker_GetTimeOfLastChange, + Moniker_Inverse, + Moniker_CommonPrefixWith, + Moniker_RelativePathTo, + Moniker_GetDisplayName, + Moniker_ParseDisplayName, + Moniker_IsSystemMoniker +}; + +static IMoniker Moniker = { &MonikerVtbl }; + +static void test_HlinkResolveMonikerForData(void) +{ + IBindCtx *bctx; + HRESULT hres; + + CreateBindCtx(0, &bctx); + _bctx = bctx; + + SET_EXPECT(IsSystemMoniker); + SET_EXPECT(GetDisplayName); + SET_EXPECT(BindToStorage); + + hres = HlinkResolveMonikerForData(&Moniker, 0, bctx, 0, NULL, &BindStatusCallback, NULL); + ok(hres == S_OK, "HlinkResolveMonikerForData failed: %08x\n", hres); + + CHECK_CALLED(IsSystemMoniker); + CHECK_CALLED(GetDisplayName); + CHECK_CALLED(BindToStorage); + + IBindCtx_Release(bctx); +} + START_TEST(hlink) { CoInitialize(NULL); @@ -457,6 +913,8 @@ START_TEST(hlink) test_persist(); test_special_reference(); test_HlinkCreateExtensionServices(); + test_HlinkParseDisplayName(); + test_HlinkResolveMonikerForData(); CoUninitialize(); } diff --git a/dlls/itss/tests/protocol.c b/dlls/itss/tests/protocol.c index c2fcf955497..ea04437a270 100644 --- a/dlls/itss/tests/protocol.c +++ b/dlls/itss/tests/protocol.c @@ -70,6 +70,7 @@ DEFINE_EXPECT(ReportResult); static HRESULT expect_hrResult; static IInternetProtocol *read_protocol = NULL; +static DWORD bindf; static const WCHAR blank_url1[] = {'i','t','s',':', 't','e','s','t','.','c','h','m',':',':','/','b','l','a','n','k','.','h','t','m','l',0}; @@ -244,6 +245,7 @@ static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfB ok(pbindinfo != NULL, "pbindinfo == NULL\n"); ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize); + *grfBINDF = bindf; return S_OK; } @@ -610,6 +612,8 @@ static void test_its_protocol(void) test_protocol_url(factory, blank_url5, TRUE); test_protocol_url(factory, blank_url6, TRUE); test_protocol_url(factory, blank_url8, TRUE); + bindf = BINDF_FROMURLMON | BINDF_NEEDFILE; + test_protocol_url(factory, blank_url1, TRUE); } IClassFactory_Release(factory); diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 51eec84ef2a..6bc867f4ffc 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -878,6 +878,7 @@ @ stdcall ReadFileEx(long ptr long ptr ptr) @ stub ReadFileScatter @ stdcall ReadProcessMemory(long ptr ptr long ptr) +@ stdcall RegisterApplicationRestart(wstr long) @ stub RegisterConsoleIME @ stub RegisterConsoleOS2 @ stub RegisterConsoleVDM diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c index a8bd099e1aa..a13c346b2d5 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c @@ -351,6 +351,8 @@ static void parse_locale_name( const WCHAR *str, struct locale_name *name ) static const WCHAR latnW[] = {'-','L','a','t','n',0}; WCHAR *p; + TRACE("%s\n", debugstr_w(str)); + name->country = name->charset = name->script = name->modifier = NULL; name->lcid = MAKELCID( MAKELANGID(LANG_ENGLISH,SUBLANG_DEFAULT), SORT_DEFAULT ); name->matches = 0; @@ -395,7 +397,6 @@ static void parse_locale_name( const WCHAR *str, struct locale_name *name ) { *p++ = 0; name->charset = p; - name->codepage = find_charset( name->charset ); p = strchrW( p, '@' ); } if (p) @@ -404,6 +405,9 @@ static void parse_locale_name( const WCHAR *str, struct locale_name *name ) name->modifier = p; } + if (name->charset) + name->codepage = find_charset( name->charset ); + /* rebuild a Windows name if possible */ if (name->charset) goto done; /* can't specify charset in Windows format */ diff --git a/dlls/kernel32/ne_module.c b/dlls/kernel32/ne_module.c index e41ced97cdc..09e317592f0 100644 --- a/dlls/kernel32/ne_module.c +++ b/dlls/kernel32/ne_module.c @@ -1193,7 +1193,7 @@ HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock ) HMODULE16 hModule; NE_MODULE *pModule; LPSTR cmdline; - WORD cmdShow; + WORD cmdShow = 1; /* SW_SHOWNORMAL but we don't want to include winuser.h here */ if (name == NULL) return 0; @@ -1235,7 +1235,8 @@ HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock ) * information. */ params = (LOADPARAMS16 *)paramBlock; - cmdShow = ((WORD *)MapSL(params->showCmd))[1]; + if (params->showCmd) + cmdShow = ((WORD *)MapSL( params->showCmd ))[1]; cmdline = MapSL( params->cmdLine ); return NE_CreateThread( pModule, cmdShow, cmdline ); } diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c index 76818801af5..f0f713f6c62 100644 --- a/dlls/kernel32/path.c +++ b/dlls/kernel32/path.c @@ -1042,15 +1042,6 @@ BOOL WINAPI MoveFileWithProgressW( LPCWSTR source, LPCWSTR dest, goto error; } - if (info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - if (flag & MOVEFILE_REPLACE_EXISTING) /* cannot replace directory */ - { - SetLastError( ERROR_INVALID_PARAMETER ); - goto error; - } - } - /* we must have write access to the destination, and it must */ /* not exist except if MOVEFILE_REPLACE_EXISTING is set */ @@ -1061,7 +1052,7 @@ BOOL WINAPI MoveFileWithProgressW( LPCWSTR source, LPCWSTR dest, } status = NtOpenFile( &dest_handle, GENERIC_READ | GENERIC_WRITE, &attr, &io, 0, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); - if (status == STATUS_SUCCESS) + if (status == STATUS_SUCCESS) /* destination exists */ { NtClose( dest_handle ); if (!(flag & MOVEFILE_REPLACE_EXISTING)) @@ -1070,6 +1061,11 @@ BOOL WINAPI MoveFileWithProgressW( LPCWSTR source, LPCWSTR dest, RtlFreeUnicodeString( &nt_name ); goto error; } + else if (info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) /* cannot replace directory */ + { + SetLastError( ERROR_ACCESS_DENIED ); + goto error; + } } else if (status != STATUS_OBJECT_NAME_NOT_FOUND) { diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 6156203d408..8e7e675d8d8 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -2968,3 +2968,14 @@ BOOL WINAPI CmdBatNotification( BOOL bBatchRunning ) FIXME("%d\n", bBatchRunning); return FALSE; } + + +/*********************************************************************** + * RegisterApplicationRestart (KERNEL32.@) + */ +HRESULT WINAPI RegisterApplicationRestart(PCWSTR pwzCommandLine, DWORD dwFlags) +{ + FIXME("(%s,%d)\n", debugstr_w(pwzCommandLine), dwFlags); + + return S_OK; +} diff --git a/dlls/kernel32/tests/actctx.c b/dlls/kernel32/tests/actctx.c index c36396cb84d..8c764647900 100644 --- a/dlls/kernel32/tests/actctx.c +++ b/dlls/kernel32/tests/actctx.c @@ -1097,9 +1097,8 @@ static void run_child_process(void) sprintf(cmdline, "\"%s\" %s manifest1", argv[0], argv[1]); ok(CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) != 0, "Could not create process: %u\n", GetLastError()); + winetest_wait_child_process( pi.hProcess ); CloseHandle(pi.hThread); - - WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); DeleteFileA(path); } diff --git a/dlls/kernel32/tests/toolhelp.c b/dlls/kernel32/tests/toolhelp.c index 3249379802d..aafc9825e88 100644 --- a/dlls/kernel32/tests/toolhelp.c +++ b/dlls/kernel32/tests/toolhelp.c @@ -342,8 +342,5 @@ START_TEST(toolhelp) test_module(info.dwProcessId, sub_expected_modules, NUM_OF(sub_expected_modules)); SetEvent(ev2); - w = WaitForSingleObject(info.hProcess, WAIT_TIME); - ok(w == WAIT_OBJECT_0, "Failed to wait on sub-process termination\n"); - ok(GetExitCodeProcess(info.hProcess, &w), "couldn't get process exit code\n"); - ok(w == WAIT_OBJECT_0, "Sub-Process failed to terminate properly\n"); + winetest_wait_child_process( info.hProcess ); } diff --git a/dlls/kernel32/tests/version.c b/dlls/kernel32/tests/version.c index ac4d8142ed0..8aec42a1a07 100644 --- a/dlls/kernel32/tests/version.c +++ b/dlls/kernel32/tests/version.c @@ -89,18 +89,13 @@ static void test_GetVersionEx(void) ok(ret, "Expected GetVersionExA to succeed\n"); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); - } -START_TEST(version) +static void test_VerifyVersionInfo(void) { OSVERSIONINFOEX info = { sizeof(info) }; BOOL ret; - init_function_pointers(); - - test_GetVersionEx(); - if(!pVerifyVersionInfoA || !pVerSetConditionMask) { skip("Needed functions not available\n"); @@ -237,3 +232,11 @@ START_TEST(version) pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL)); ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError()); } + +START_TEST(version) +{ + init_function_pointers(); + + test_GetVersionEx(); + test_VerifyVersionInfo(); +} diff --git a/dlls/localspl/localspl_main.c b/dlls/localspl/localspl_main.c index 3585c342cd0..3cb477e5999 100644 --- a/dlls/localspl/localspl_main.c +++ b/dlls/localspl/localspl_main.c @@ -1,7 +1,7 @@ /* * Implementation of the Local Printmonitor * - * Copyright 2006 Detlef Riekenberg + * Copyright 2006-2008 Detlef Riekenberg * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,14 +29,642 @@ #include "winreg.h" #include "winspool.h" #include "ddk/winsplp.h" +#include "winuser.h" #include "wine/debug.h" +#include "wine/unicode.h" #include "localspl_private.h" WINE_DEFAULT_DEBUG_CHANNEL(localspl); +/* ############################### */ + +typedef struct { + WCHAR src[MAX_PATH+MAX_PATH]; + WCHAR dst[MAX_PATH+MAX_PATH]; + DWORD srclen; + DWORD dstlen; + DWORD copyflags; + BOOL lazy; +} apd_data_t; + +typedef struct { + LPCWSTR envname; + LPCWSTR subdir; + DWORD driverversion; + LPCWSTR versionregpath; + LPCWSTR versionsubdir; +} printenv_t; + +/* ############################### */ + HINSTANCE LOCALSPL_hInstance = NULL; +static const PRINTPROVIDOR * pp = NULL; + + +static const WCHAR backslashW[] = {'\\',0}; +static const WCHAR configuration_fileW[] = {'C','o','n','f','i','g','u','r','a','t','i','o','n',' ','F','i','l','e',0}; +static const WCHAR datatypeW[] = {'D','a','t','a','t','y','p','e',0}; +static const WCHAR data_fileW[] = {'D','a','t','a',' ','F','i','l','e',0}; +static const WCHAR default_devmodeW[] = {'D','e','f','a','u','l','t',' ','D','e','v','M','o','d','e',0}; +static const WCHAR dependent_filesW[] = {'D','e','p','e','n','d','e','n','t',' ','F','i','l','e','s',0}; +static const WCHAR descriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0}; +static const WCHAR driverW[] = {'D','r','i','v','e','r',0}; +static const WCHAR fmt_driversW[] = { 'S','y','s','t','e','m','\\', + 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'c','o','n','t','r','o','l','\\', + 'P','r','i','n','t','\\', + 'E','n','v','i','r','o','n','m','e','n','t','s','\\', + '%','s','\\','D','r','i','v','e','r','s','%','s',0 }; +static const WCHAR hardwareidW[] = {'H','a','r','d','w','a','r','e','I','D',0}; +static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0}; +static const WCHAR locationW[] = {'L','o','c','a','t','i','o','n',0}; +static const WCHAR manufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0}; +static const WCHAR monitorW[] = {'M','o','n','i','t','o','r',0}; +static const WCHAR monitorUIW[] = {'M','o','n','i','t','o','r','U','I',0}; +static const WCHAR nameW[] = {'N','a','m','e',0}; +static const WCHAR oem_urlW[] = {'O','E','M',' ','U','r','l',0}; +static const WCHAR parametersW[] = {'P','a','r','a','m','e','t','e','r','s',0}; +static const WCHAR portW[] = {'P','o','r','t',0}; +static const WCHAR previous_namesW[] = {'P','r','e','v','i','o','u','s',' ','N','a','m','e','s',0}; +static const WCHAR spooldriversW[] = {'\\','s','p','o','o','l','\\','d','r','i','v','e','r','s','\\',0}; +static const WCHAR versionW[] = {'V','e','r','s','i','o','n',0}; + +static const WCHAR win40_envnameW[] = {'W','i','n','d','o','w','s',' ','4','.','0',0}; +static const WCHAR win40_subdirW[] = {'w','i','n','4','0',0}; +static const WCHAR version0_regpathW[] = {'\\','V','e','r','s','i','o','n','-','0',0}; +static const WCHAR version0_subdirW[] = {'\\','0',0}; + +static const WCHAR x86_envnameW[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0}; +static const WCHAR x86_subdirW[] = {'w','3','2','x','8','6',0}; +static const WCHAR version3_regpathW[] = {'\\','V','e','r','s','i','o','n','-','3',0}; +static const WCHAR version3_subdirW[] = {'\\','3',0}; + + +static const printenv_t env_x86 = {x86_envnameW, x86_subdirW, 3, + version3_regpathW, version3_subdirW}; + +static const printenv_t env_win40 = {win40_envnameW, win40_subdirW, 0, + version0_regpathW, version0_subdirW}; + +static const printenv_t * const all_printenv[] = {&env_x86, &env_win40}; + + +static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_2W), + sizeof(DRIVER_INFO_3W), sizeof(DRIVER_INFO_4W), + sizeof(DRIVER_INFO_5W), sizeof(DRIVER_INFO_6W), + 0, sizeof(DRIVER_INFO_8W)}; + +/****************************************************************** + * apd_copyfile [internal] + * + * Copy a file from the driverdirectory to the versioned directory + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + */ +static BOOL apd_copyfile(LPWSTR filename, apd_data_t *apd) +{ + LPWSTR ptr; + LPWSTR srcname; + DWORD res; + + apd->src[apd->srclen] = '\0'; + apd->dst[apd->dstlen] = '\0'; + + if (!filename || !filename[0]) { + /* nothing to copy */ + return TRUE; + } + + ptr = strrchrW(filename, '\\'); + if (ptr) { + ptr++; + } + else + { + ptr = filename; + } + + if (apd->copyflags & APD_COPY_FROM_DIRECTORY) { + /* we have an absolute Path */ + srcname = filename; + } + else + { + srcname = apd->src; + lstrcatW(srcname, ptr); + } + lstrcatW(apd->dst, ptr); + + TRACE("%s => %s\n", debugstr_w(filename), debugstr_w(apd->dst)); + + /* FIXME: handle APD_COPY_NEW_FILES */ + res = CopyFileW(srcname, apd->dst, FALSE); + TRACE("got %u with %u\n", res, GetLastError()); + + return (apd->lazy) ? TRUE : res; +} + +/****************************************************************** + * copy_servername_from_name (internal) + * + * for an external server, the serverpart from the name is copied. + * + * RETURNS + * the length (in WCHAR) of the serverpart (0 for the local computer) + * (-length), when the name is to long + * + */ +static LONG copy_servername_from_name(LPCWSTR name, LPWSTR target) +{ + LPCWSTR server; + LPWSTR ptr; + WCHAR buffer[MAX_COMPUTERNAME_LENGTH +1]; + DWORD len; + DWORD serverlen; + + if (target) *target = '\0'; + + if (name == NULL) return 0; + if ((name[0] != '\\') || (name[1] != '\\')) return 0; + + server = &name[2]; + /* skip over both backslash, find seperator '\' */ + ptr = strchrW(server, '\\'); + serverlen = (ptr) ? ptr - server : lstrlenW(server); + + /* servername is empty or to long */ + if (serverlen == 0) return 0; + + TRACE("found %s\n", debugstr_wn(server, serverlen)); + + if (serverlen > MAX_COMPUTERNAME_LENGTH) return -serverlen; + + len = sizeof(buffer) / sizeof(buffer[0]); + if (GetComputerNameW(buffer, &len)) { + if ((serverlen == len) && (strncmpiW(server, buffer, len) == 0)) { + /* The requested Servername is our computername */ + if (target) { + memcpy(target, server, serverlen * sizeof(WCHAR)); + target[serverlen] = '\0'; + } + return serverlen; + } + } + return 0; +} + +/****************************************************************** + * Return the number of bytes for an multi_sz string. + * The result includes all \0s + * (specifically the extra \0, that is needed as multi_sz terminator). + */ +static int multi_sz_lenW(const WCHAR *str) +{ + const WCHAR *ptr = str; + if (!str) return 0; + do + { + ptr += lstrlenW(ptr) + 1; + } while (*ptr); + + return (ptr - str + 1) * sizeof(WCHAR); +} + +/****************************************************************** + * validate_envW [internal] + * + * validate the user-supplied printing-environment + * + * PARAMS + * env [I] PTR to Environment-String or NULL + * + * RETURNS + * Success: PTR to printenv_t + * Failure: NULL and ERROR_INVALID_ENVIRONMENT + * + * NOTES + * An empty string is handled the same way as NULL. + * + */ + +static const printenv_t * validate_envW(LPCWSTR env) +{ + const printenv_t *result = NULL; + unsigned int i; + + TRACE("(%s)\n", debugstr_w(env)); + if (env && env[0]) + { + for (i = 0; i < sizeof(all_printenv)/sizeof(all_printenv[0]); i++) + { + if (lstrcmpiW(env, all_printenv[i]->envname) == 0) + { + result = all_printenv[i]; + break; + } + } + if (result == NULL) { + FIXME("unsupported Environment: %s\n", debugstr_w(env)); + SetLastError(ERROR_INVALID_ENVIRONMENT); + } + /* on win9x, only "Windows 4.0" is allowed, but we ignore this */ + } + else + { + result = (GetVersion() & 0x80000000) ? &env_win40 : &env_x86; + } + + TRACE("=> using %p: %s\n", result, debugstr_w(result ? result->envname : NULL)); + return result; +} + +/***************************************************************************** + * open_driver_reg [internal] + * + * opens the registry for the printer drivers depending on the given input + * variable pEnvironment + * + * RETURNS: + * Success: the opened hkey + * Failure: NULL + */ +static HKEY open_driver_reg(LPCWSTR pEnvironment) +{ + HKEY retval = NULL; + LPWSTR buffer; + const printenv_t * env; + + TRACE("(%s)\n", debugstr_w(pEnvironment)); + + env = validate_envW(pEnvironment); + if (!env) return NULL; + + buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(fmt_driversW) + + (lstrlenW(env->envname) + lstrlenW(env->versionregpath)) * sizeof(WCHAR)); + + if (buffer) { + wsprintfW(buffer, fmt_driversW, env->envname, env->versionregpath); + RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval); + HeapFree(GetProcessHeap(), 0, buffer); + } + return retval; +} + +/***************************************************************************** + * fpGetPrinterDriverDirectory [exported through PRINTPROVIDOR] + * + * Return the PATH for the Printer-Drivers + * + * PARAMS + * pName [I] Servername (NT only) or NULL (local Computer) + * pEnvironment [I] Printing-Environment (see below) or NULL (Default) + * Level [I] Structure-Level (must be 1) + * pDriverDirectory [O] PTR to Buffer that receives the Result + * cbBuf [I] Size of Buffer at pDriverDirectory + * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / + * required for pDriverDirectory + * + * RETURNS + * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory + * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory, + * if cbBuf is too small + * + * Native Values returned in pDriverDirectory on Success: + *| NT(Windows NT x86): "%winsysdir%\\spool\\DRIVERS\\w32x86" + *| NT(Windows 4.0): "%winsysdir%\\spool\\DRIVERS\\win40" + *| win9x(Windows 4.0): "%winsysdir%" + * + * "%winsysdir%" is the Value from GetSystemDirectoryW() + * + */ +static BOOL WINAPI fpGetPrinterDriverDirectory(LPWSTR pName, LPWSTR pEnvironment, + DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded) +{ + DWORD needed; + const printenv_t * env; + + TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName), + debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded); + + if (pName != NULL && pName[0]) { + FIXME("server %s not supported\n", debugstr_w(pName)); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + env = validate_envW(pEnvironment); + if (!env) return FALSE; /* pEnvironment invalid or unsupported */ + + + /* GetSystemDirectoryW returns number of WCHAR including the '\0' */ + needed = GetSystemDirectoryW(NULL, 0); + /* add the Size for the Subdirectories */ + needed += lstrlenW(spooldriversW); + needed += lstrlenW(env->subdir); + needed *= sizeof(WCHAR); /* return-value is size in Bytes */ + + *pcbNeeded = needed; + + if (needed > cbBuf) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + if (pDriverDirectory == NULL) { + /* ERROR_INVALID_USER_BUFFER is NT, ERROR_INVALID_PARAMETER is win9x */ + SetLastError(ERROR_INVALID_USER_BUFFER); + return FALSE; + } + + GetSystemDirectoryW((LPWSTR) pDriverDirectory, cbBuf/sizeof(WCHAR)); + /* add the Subdirectories */ + lstrcatW((LPWSTR) pDriverDirectory, spooldriversW); + lstrcatW((LPWSTR) pDriverDirectory, env->subdir); + + TRACE("=> %s\n", debugstr_w((LPWSTR) pDriverDirectory)); + return TRUE; +} + +/****************************************************************************** + * myAddPrinterDriverEx [internal] + * + * Install a Printer Driver with the Option to upgrade / downgrade the Files + * and a special mode with lazy error ckecking + * + */ +static BOOL WINAPI myAddPrinterDriverEx(DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags, BOOL lazy) +{ + const printenv_t *env; + apd_data_t apd; + DRIVER_INFO_8W di; + LPWSTR ptr; + HKEY hroot; + HKEY hdrv; + DWORD disposition; + DWORD len; + LONG lres; + + /* we need to set all entries in the Registry, independent from the Level of + DRIVER_INFO, that the caller supplied */ + + ZeroMemory(&di, sizeof(di)); + if (pDriverInfo && (level < (sizeof(di_sizeof) / sizeof(di_sizeof[0])))) { + memcpy(&di, pDriverInfo, di_sizeof[level]); + } + + /* dump the most used infos */ + TRACE("%p: .cVersion : 0x%x/%d\n", pDriverInfo, di.cVersion, di.cVersion); + TRACE("%p: .pName : %s\n", di.pName, debugstr_w(di.pName)); + TRACE("%p: .pEnvironment: %s\n", di.pEnvironment, debugstr_w(di.pEnvironment)); + TRACE("%p: .pDriverPath : %s\n", di.pDriverPath, debugstr_w(di.pDriverPath)); + TRACE("%p: .pDataFile : %s\n", di.pDataFile, debugstr_w(di.pDataFile)); + TRACE("%p: .pConfigFile : %s\n", di.pConfigFile, debugstr_w(di.pConfigFile)); + TRACE("%p: .pHelpFile : %s\n", di.pHelpFile, debugstr_w(di.pHelpFile)); + /* dump only the first of the additional Files */ + TRACE("%p: .pDependentFiles: %s\n", di.pDependentFiles, debugstr_w(di.pDependentFiles)); + + + /* check environment */ + env = validate_envW(di.pEnvironment); + if (env == NULL) return FALSE; /* ERROR_INVALID_ENVIRONMENT */ + + /* fill the copy-data / get the driverdir */ + len = sizeof(apd.src) - sizeof(version3_subdirW) - sizeof(WCHAR); + if (!fpGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1, + (LPBYTE) apd.src, len, &len)) { + /* Should never Fail */ + return FALSE; + } + memcpy(apd.dst, apd.src, len); + lstrcatW(apd.src, backslashW); + apd.srclen = lstrlenW(apd.src); + lstrcatW(apd.dst, env->versionsubdir); + lstrcatW(apd.dst, backslashW); + apd.dstlen = lstrlenW(apd.dst); + apd.copyflags = dwFileCopyFlags; + apd.lazy = lazy; + CreateDirectoryW(apd.src, NULL); + CreateDirectoryW(apd.dst, NULL); + + hroot = open_driver_reg(env->envname); + if (!hroot) { + ERR("Can't create Drivers key\n"); + return FALSE; + } + + /* Fill the Registry for the Driver */ + if ((lres = RegCreateKeyExW(hroot, di.pName, 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_WRITE | KEY_QUERY_VALUE, NULL, + &hdrv, &disposition)) != ERROR_SUCCESS) { + + ERR("can't create driver %s: %u\n", debugstr_w(di.pName), lres); + RegCloseKey(hroot); + SetLastError(lres); + return FALSE; + } + RegCloseKey(hroot); + + if (disposition == REG_OPENED_EXISTING_KEY) { + TRACE("driver %s already installed\n", debugstr_w(di.pName)); + RegCloseKey(hdrv); + SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED); + return FALSE; + } + + /* Verified with the Adobe PS Driver, that w2k does not use di.Version */ + RegSetValueExW(hdrv, versionW, 0, REG_DWORD, (LPBYTE) &env->driverversion, + sizeof(DWORD)); + + RegSetValueExW(hdrv, driverW, 0, REG_SZ, (LPBYTE) di.pDriverPath, + (lstrlenW(di.pDriverPath)+1)* sizeof(WCHAR)); + apd_copyfile(di.pDriverPath, &apd); + + RegSetValueExW(hdrv, data_fileW, 0, REG_SZ, (LPBYTE) di.pDataFile, + (lstrlenW(di.pDataFile)+1)* sizeof(WCHAR)); + apd_copyfile(di.pDataFile, &apd); + + RegSetValueExW(hdrv, configuration_fileW, 0, REG_SZ, (LPBYTE) di.pConfigFile, + (lstrlenW(di.pConfigFile)+1)* sizeof(WCHAR)); + apd_copyfile(di.pConfigFile, &apd); + + /* settings for level 3 */ + RegSetValueExW(hdrv, help_fileW, 0, REG_SZ, (LPBYTE) di.pHelpFile, + di.pHelpFile ? (lstrlenW(di.pHelpFile)+1)* sizeof(WCHAR) : 0); + apd_copyfile(di.pHelpFile, &apd); + + + ptr = di.pDependentFiles; + RegSetValueExW(hdrv, dependent_filesW, 0, REG_MULTI_SZ, (LPBYTE) di.pDependentFiles, + di.pDependentFiles ? multi_sz_lenW(di.pDependentFiles) : 0); + while ((ptr != NULL) && (ptr[0])) { + if (apd_copyfile(ptr, &apd)) { + ptr += lstrlenW(ptr) + 1; + } + else + { + WARN("Failed to copy %s\n", debugstr_w(ptr)); + ptr = NULL; + } + } + /* The language-Monitor was already copied by the caller to "%SystemRoot%\system32" */ + RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (LPBYTE) di.pMonitorName, + di.pMonitorName ? (lstrlenW(di.pMonitorName)+1)* sizeof(WCHAR) : 0); + + RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (LPBYTE) di.pDefaultDataType, + di.pDefaultDataType ? (lstrlenW(di.pDefaultDataType)+1)* sizeof(WCHAR) : 0); + + /* settings for level 4 */ + RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (LPBYTE) di.pszzPreviousNames, + di.pszzPreviousNames ? multi_sz_lenW(di.pszzPreviousNames) : 0); + + if (level > 5) TRACE("level %u for Driver %s is incomplete\n", level, debugstr_w(di.pName)); + + RegCloseKey(hdrv); + TRACE("### DrvDriverEvent(...,DRIVEREVENT_INITIALIZE) not implemented yet\n"); + + TRACE("=> TRUE with %u\n", GetLastError()); + return TRUE; + +} + +/****************************************************************************** + * fpAddPrinterDriverEx [exported through PRINTPROVIDOR] + * + * Install a Printer Driver with the Option to upgrade / downgrade the Files + * + * PARAMS + * pName [I] Servername or NULL (local Computer) + * level [I] Level for the supplied DRIVER_INFO_*W struct + * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter + * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files + * + * RESULTS + * Success: TRUE + * Failure: FALSE + * + */ +static BOOL WINAPI fpAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags) +{ + LONG lres; + + TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags); + lres = copy_servername_from_name(pName, NULL); + if (lres) { + FIXME("server %s not supported\n", debugstr_w(pName)); + SetLastError(ERROR_ACCESS_DENIED); + return FALSE; + } + + if ((dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY) != APD_COPY_ALL_FILES) { + TRACE("Flags 0x%x ignored (using APD_COPY_ALL_FILES)\n", dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY); + } + + return myAddPrinterDriverEx(level, pDriverInfo, dwFileCopyFlags, TRUE); +} + +/***************************************************** + * get_backend [internal] + */ +static const PRINTPROVIDOR * get_backend(void) +{ + static const PRINTPROVIDOR backend = { + NULL, /* fpOpenPrinter */ + NULL, /* fpSetJob */ + NULL, /* fpGetJob */ + NULL, /* fpEnumJobs */ + NULL, /* fpAddPrinter */ + NULL, /* fpDeletePrinter */ + NULL, /* fpSetPrinter */ + NULL, /* fpGetPrinter */ + NULL, /* fpEnumPrinters */ + NULL, /* fpAddPrinterDriver */ + NULL, /* fpEnumPrinterDrivers */ + NULL, /* fpGetPrinterDriver */ + fpGetPrinterDriverDirectory, + NULL, /* fpDeletePrinterDriver */ + NULL, /* fpAddPrintProcessor */ + NULL, /* fpEnumPrintProcessors */ + NULL, /* fpGetPrintProcessorDirectory */ + NULL, /* fpDeletePrintProcessor */ + NULL, /* fpEnumPrintProcessorDatatypes */ + NULL, /* fpStartDocPrinter */ + NULL, /* fpStartPagePrinter */ + NULL, /* fpWritePrinter */ + NULL, /* fpEndPagePrinter */ + NULL, /* fpAbortPrinter */ + NULL, /* fpReadPrinter */ + NULL, /* fpEndDocPrinter */ + NULL, /* fpAddJob */ + NULL, /* fpScheduleJob */ + NULL, /* fpGetPrinterData */ + NULL, /* fpSetPrinterData */ + NULL, /* fpWaitForPrinterChange */ + NULL, /* fpClosePrinter */ + NULL, /* fpAddForm */ + NULL, /* fpDeleteForm */ + NULL, /* fpGetForm */ + NULL, /* fpSetForm */ + NULL, /* fpEnumForms */ + NULL, /* fpEnumMonitors */ + NULL, /* fpEnumPorts */ + NULL, /* fpAddPort */ + NULL, /* fpConfigurePort */ + NULL, /* fpDeletePort */ + NULL, /* fpCreatePrinterIC */ + NULL, /* fpPlayGdiScriptOnPrinterIC */ + NULL, /* fpDeletePrinterIC */ + NULL, /* fpAddPrinterConnection */ + NULL, /* fpDeletePrinterConnection */ + NULL, /* fpPrinterMessageBox */ + NULL, /* fpAddMonitor */ + NULL, /* fpDeleteMonitor */ + NULL, /* fpResetPrinter */ + NULL, /* fpGetPrinterDriverEx */ + NULL, /* fpFindFirstPrinterChangeNotification */ + NULL, /* fpFindClosePrinterChangeNotification */ + NULL, /* fpAddPortEx */ + NULL, /* fpShutDown */ + NULL, /* fpRefreshPrinterChangeNotification */ + NULL, /* fpOpenPrinterEx */ + NULL, /* fpAddPrinterEx */ + NULL, /* fpSetPort */ + NULL, /* fpEnumPrinterData */ + NULL, /* fpDeletePrinterData */ + NULL, /* fpClusterSplOpen */ + NULL, /* fpClusterSplClose */ + NULL, /* fpClusterSplIsAlive */ + NULL, /* fpSetPrinterDataEx */ + NULL, /* fpGetPrinterDataEx */ + NULL, /* fpEnumPrinterDataEx */ + NULL, /* fpEnumPrinterKey */ + NULL, /* fpDeletePrinterDataEx */ + NULL, /* fpDeletePrinterKey */ + NULL, /* fpSeekPrinter */ + NULL, /* fpDeletePrinterDriverEx */ + NULL, /* fpAddPerMachineConnection */ + NULL, /* fpDeletePerMachineConnection */ + NULL, /* fpEnumPerMachineConnections */ + NULL, /* fpXcvData */ + fpAddPrinterDriverEx, + NULL, /* fpSplReadPrinter */ + NULL, /* fpDriverUnloadComplete */ + NULL, /* fpGetSpoolFileInfo */ + NULL, /* fpCommitSpoolData */ + NULL, /* fpCloseSpoolFileHandle */ + NULL, /* fpFlushPrinter */ + NULL, /* fpSendRecvBidiData */ + NULL /* fpAddDriverCatalog */ + }; + TRACE("=> %p\n", &backend); + return &backend; + +} + /***************************************************** * DllMain */ @@ -52,6 +680,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls( hinstDLL ); LOCALSPL_hInstance = hinstDLL; + pp = get_backend(); break; } return TRUE; @@ -84,7 +713,7 @@ BOOL WINAPI InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, { TRACE("(%p, %u, %s)\n", pPrintProvidor, cbPrintProvidor, debugstr_w(pFullRegistryPath)); - ZeroMemory(pPrintProvidor, (cbPrintProvidor < sizeof(PRINTPROVIDOR)) ? cbPrintProvidor : sizeof(PRINTPROVIDOR)); + memcpy(pPrintProvidor, pp, (cbPrintProvidor < sizeof(PRINTPROVIDOR)) ? cbPrintProvidor : sizeof(PRINTPROVIDOR)); return TRUE; } diff --git a/dlls/mapi32/mapi32.spec b/dlls/mapi32/mapi32.spec index bf97415299d..abf79bf124a 100644 --- a/dlls/mapi32/mapi32.spec +++ b/dlls/mapi32/mapi32.spec @@ -54,7 +54,7 @@ 72 stdcall FEqualNames@8(ptr ptr) FEqualNames 73 stub WrapStoreEntryID@24 74 stdcall IsBadBoundedStringPtr@8(ptr long) IsBadBoundedStringPtr - 75 stub HrQueryAllRows@24 + 75 stdcall HrQueryAllRows@24(ptr ptr ptr ptr long ptr) HrQueryAllRows 76 stdcall PropCopyMore@16(ptr ptr ptr ptr) PropCopyMore 77 stdcall UlPropSize@4(ptr) UlPropSize 78 stdcall FPropContainsProp@12(ptr ptr long) FPropContainsProp diff --git a/dlls/mapi32/util.c b/dlls/mapi32/util.c index 6621e6f35bc..b68eceb51ab 100644 --- a/dlls/mapi32/util.c +++ b/dlls/mapi32/util.c @@ -890,3 +890,15 @@ BOOL WINAPI FGetComponentPath(LPCSTR component, LPCSTR qualifier, LPSTR dll_path } return ret; } + +/************************************************************************** + * HrQueryAllRows (MAPI32.75) + */ +HRESULT WINAPI HrQueryAllRows(LPMAPITABLE lpTable, LPSPropTagArray lpPropTags, + LPSRestriction lpRestriction, LPSSortOrderSet lpSortOrderSet, + LONG crowsMax, LPSRowSet *lppRows) +{ + FIXME("(%p, %p, %p, %p, %d, %p): stub\n", lpTable, lpPropTags, lpRestriction, lpSortOrderSet, crowsMax, lppRows); + *lppRows = NULL; + return MAPI_E_CALL_FAILED; +} diff --git a/dlls/mshtml/Makefile.in b/dlls/mshtml/Makefile.in index 3b51849d875..07a32ed5d5e 100644 --- a/dlls/mshtml/Makefile.in +++ b/dlls/mshtml/Makefile.in @@ -4,7 +4,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = mshtml.dll IMPORTLIB = libmshtml.$(IMPLIBEXT) -IMPORTS = urlmon ole32 oleaut32 user32 gdi32 advapi32 kernel32 +IMPORTS = urlmon shlwapi ole32 oleaut32 user32 gdi32 advapi32 kernel32 EXTRALIBS = -lstrmiids -luuid EXTRADEFS = -DCOM_NO_WINDOWS_H diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index e2abfa400d8..6eb7f30a425 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -579,6 +579,20 @@ static inline LPWSTR heap_strdupW(LPCWSTR str) return ret; } +static inline WCHAR *heap_strdupAtoW(const char *str) +{ + LPWSTR ret = NULL; + + if(str) { + DWORD len; + + len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + ret = heap_alloc(len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, -1); + } + + return ret; +} HINSTANCE get_shdoclc(void); diff --git a/dlls/mshtml/nsio.c b/dlls/mshtml/nsio.c index c900bd93486..2e62a44bf5b 100644 --- a/dlls/mshtml/nsio.c +++ b/dlls/mshtml/nsio.c @@ -1465,14 +1465,31 @@ static nsresult NSAPI nsURI_GetPath(nsIWineURI *iface, nsACString *aPath) static nsresult NSAPI nsURI_SetPath(nsIWineURI *iface, const nsACString *aPath) { nsURI *This = NSURI_THIS(iface); + const char *path; - TRACE("(%p)->(%p)\n", This, aPath); + nsACString_GetData(aPath, &path); + TRACE("(%p)->(%p(%s))\n", This, aPath, debugstr_a(path)); - if(This->uri) - return nsIURI_SetPath(This->uri, aPath); - FIXME("default action not implemented\n"); - return NS_ERROR_NOT_IMPLEMENTED; + if(This->wine_url) { + WCHAR new_url[INTERNET_MAX_URL_LENGTH]; + DWORD size = sizeof(new_url)/sizeof(WCHAR); + LPWSTR pathw; + HRESULT hres; + + pathw = heap_strdupAtoW(path); + hres = UrlCombineW(This->wine_url, pathw, new_url, &size, 0); + heap_free(pathw); + if(SUCCEEDED(hres)) + nsIWineURI_SetWineURL(NSWINEURI(This), new_url); + else + WARN("UrlCombine failed: %08x\n", hres); + } + + if(!This->uri) + return NS_OK; + + return nsIURI_SetPath(This->uri, aPath); } static nsresult NSAPI nsURI_Equals(nsIWineURI *iface, nsIURI *other, PRBool *_retval) diff --git a/dlls/mshtml/tests/protocol.c b/dlls/mshtml/tests/protocol.c index 2e9d6e9b8c5..01a6a06fb85 100644 --- a/dlls/mshtml/tests/protocol.c +++ b/dlls/mshtml/tests/protocol.c @@ -64,6 +64,11 @@ DEFINE_EXPECT(ReportResult); static HRESULT expect_hrResult; static BOOL expect_hr_win32err = FALSE; +static DWORD bindf; + +static const WCHAR about_blank_url[] = {'a','b','o','u','t',':','b','l','a','n','k',0}; +static const WCHAR about_test_url[] = {'a','b','o','u','t',':','t','e','s','t',0}; +static const WCHAR about_res_url[] = {'r','e','s',':','b','l','a','n','k',0}; static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv) { @@ -173,11 +178,10 @@ static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfB CHECK_EXPECT(GetBindInfo); ok(grfBINDF != NULL, "grfBINDF == NULL\n"); - if(grfBINDF) - ok(!*grfBINDF, "*grfBINDF != 0\n"); ok(pbindinfo != NULL, "pbindinfo == NULL\n"); ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize); + *grfBINDF = bindf; return S_OK; } @@ -502,20 +506,69 @@ static void test_res_protocol(void) IUnknown_Release(unk); } -static void test_about_protocol(void) +static void do_test_about_protocol(IClassFactory *factory, DWORD bf) { - IInternetProtocolInfo *protocol_info; - IUnknown *unk; - IClassFactory *factory; + IInternetProtocol *protocol; + IInternetPriority *priority; + BYTE buf[512]; + ULONG cb; HRESULT hres; - static const WCHAR blank_url[] = {'a','b','o','u','t',':','b','l','a','n','k',0}; - static const WCHAR test_url[] = {'a','b','o','u','t',':','t','e','s','t',0}; - static const WCHAR res_url[] = {'r','e','s',':','b','l','a','n','k',0}; static const WCHAR blank_html[] = {0xfeff,'<','H','T','M','L','>','<','/','H','T','M','L','>',0}; static const WCHAR test_html[] = {0xfeff,'<','H','T','M','L','>','t','e','s','t','<','/','H','T','M','L','>',0}; + bindf = bf; + + hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol); + ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres); + if(FAILED(hres)) + return; + + hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority); + ok(hres == E_NOINTERFACE, + "QueryInterface(IInternetPriority) returned %08x, expected E_NOINTEFACE\n", hres); + + protocol_start(protocol, about_blank_url); + hres = IInternetProtocol_LockRequest(protocol, 0); + ok(hres == S_OK, "LockRequest failed: %08x\n", hres); + hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb); + ok(hres == S_OK, "Read failed: %08x\n", hres); + ok(cb == sizeof(blank_html), "cb=%d\n", cb); + ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n"); + hres = IInternetProtocol_UnlockRequest(protocol); + ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres); + + protocol_start(protocol, about_test_url); + hres = IInternetProtocol_LockRequest(protocol, 0); + ok(hres == S_OK, "LockRequest failed: %08x\n", hres); + hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb); + ok(hres == S_OK, "Read failed: %08x\n", hres); + ok(cb == sizeof(test_html), "cb=%d\n", cb); + ok(!memcmp(buf, test_html, cb), "Readed wrong data\n"); + hres = IInternetProtocol_UnlockRequest(protocol); + ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres); + + protocol_start(protocol, about_res_url); + hres = IInternetProtocol_LockRequest(protocol, 0); + ok(hres == S_OK, "LockRequest failed: %08x\n", hres); + hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb); + ok(hres == S_OK, "Read failed: %08x\n", hres); + ok(cb == sizeof(blank_html), "cb=%d\n", cb); + ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n"); + hres = IInternetProtocol_UnlockRequest(protocol); + ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres); + + IInternetProtocol_Release(protocol); +} + +static void test_about_protocol(void) +{ + IInternetProtocolInfo *protocol_info; + IUnknown *unk; + IClassFactory *factory; + HRESULT hres; + hres = CoGetClassObject(&CLSID_AboutProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk); ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres); if(!SUCCEEDED(hres)) @@ -530,34 +583,34 @@ static void test_about_protocol(void) for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) { if(i != PARSE_SECURITY_URL && i != PARSE_DOMAIN) { - hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, i, 0, buf, + hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, i, 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0); ok(hres == INET_E_DEFAULT_ACTION, "[%d] failed: %08x, expected INET_E_DEFAULT_ACTION\n", i, hres); } } - hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf, + hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_SECURITY_URL, 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0); ok(hres == S_OK, "ParseUrl failed: %08x\n", hres); - ok(!lstrcmpW(blank_url, buf), "buf != blank_url\n"); + ok(!lstrcmpW(about_blank_url, buf), "buf != blank_url\n"); - hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf, + hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_SECURITY_URL, 0, buf, 3, &size, 0); ok(hres == S_FALSE, "ParseUrl failed: %08x, expected S_FALSE\n", hres); - hres = IInternetProtocolInfo_ParseUrl(protocol_info, test_url, PARSE_SECURITY_URL, 0, buf, + hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_test_url, PARSE_SECURITY_URL, 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0); ok(hres == S_OK, "ParseUrl failed: %08x\n", hres); - ok(!lstrcmpW(test_url, buf), "buf != test_url\n"); + ok(!lstrcmpW(about_test_url, buf), "buf != test_url\n"); size = 0xdeadbeef; buf[0] = '?'; - hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf, + hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_DOMAIN, 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0); ok(hres == S_OK || hres == E_FAIL, "ParseUrl failed: %08x\n", hres); ok(buf[0] == '?', "buf changed\n"); - ok(size == sizeof(blank_url)/sizeof(WCHAR), "size=%d\n", size); + ok(size == sizeof(about_blank_url)/sizeof(WCHAR), "size=%d\n", size); if (0) { @@ -571,7 +624,7 @@ static void test_about_protocol(void) ok(size == 1, "size=%u, ezpected 1\n", size); buf[0] = '?'; - hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf, + hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_DOMAIN, 0, buf, sizeof(buf)/sizeof(buf[0]), NULL, 0); ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres); ok(buf[0] == '?', "buf changed\n"); @@ -583,19 +636,19 @@ static void test_about_protocol(void) ok(buf[0] == '?', "buf changed\n"); } - hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_UNESCAPE+1, 0, buf, + hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_UNESCAPE+1, 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0); ok(hres == INET_E_DEFAULT_ACTION, "ParseUrl failed: %08x, expected INET_E_DEFAULT_ACTION\n", hres); size = 0xdeadbeef; - hres = IInternetProtocolInfo_CombineUrl(protocol_info, blank_url, test_url, + hres = IInternetProtocolInfo_CombineUrl(protocol_info, about_blank_url, about_test_url, 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0); ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres); ok(size == 0xdeadbeef, "size=%d\n", size); size = 0xdeadbeef; - hres = IInternetProtocolInfo_CombineUrl(protocol_info, blank_url, test_url, + hres = IInternetProtocolInfo_CombineUrl(protocol_info, about_blank_url, about_test_url, URL_FILE_USE_PATHURL, buf, sizeof(buf)/sizeof(buf[0]), &size, 0); ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres); ok(size == 0xdeadbeef, "size=%d\n", size); @@ -606,7 +659,7 @@ static void test_about_protocol(void) ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres); ok(size == 0xdeadbeef, "size=%d\n", size); - hres = IInternetProtocolInfo_CompareUrl(protocol_info, blank_url, blank_url, 0); + hres = IInternetProtocolInfo_CompareUrl(protocol_info, about_blank_url, about_blank_url, 0); ok(hres == E_NOTIMPL, "CompareUrl failed: %08x\n", hres); hres = IInternetProtocolInfo_CompareUrl(protocol_info, NULL, NULL, 0xdeadbeef); @@ -623,40 +676,40 @@ static void test_about_protocol(void) case QUERY_IS_SAFE: break; default: - hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, i, 0, + hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, i, 0, buf, sizeof(buf), &size, 0); ok(hres == E_FAIL, "QueryInfo(%d) returned: %08x, expected E_FAIL\n", i, hres); } } - hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_CAN_NAVIGATE, 0, + hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_CAN_NAVIGATE, 0, buf, sizeof(buf), &size, 0); ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "QueryInfo returned: %08x, expected INET_E_USE_DEFAULT_PROTOCOLHANDLER\n", hres); size = 0xdeadbeef; memset(buf, '?', sizeof(buf)); - hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0, + hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0, buf, sizeof(buf), &size, 0); ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres); ok(size == sizeof(DWORD), "size=%d\n", size); ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf); memset(buf, '?', sizeof(buf)); - hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0, + hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0, buf, sizeof(buf), NULL, 0); ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres); ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf); - hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0, + hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0, buf, 3, &size, 0); ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres); - hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0, + hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0, NULL, sizeof(buf), &size, 0); ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres); - hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, 60, 0, + hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, 60, 0, NULL, sizeof(buf), &size, 0); ok(hres == E_FAIL, "QueryInfo failed: %08x, expected E_FAIL\n", hres); @@ -666,51 +719,9 @@ static void test_about_protocol(void) hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory); ok(hres == S_OK, "Could not get IClassFactory interface\n"); if(SUCCEEDED(hres)) { - IInternetProtocol *protocol; - BYTE buf[512]; - ULONG cb; - hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol); - ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres); - - if(SUCCEEDED(hres)) { - IInternetPriority *priority; - - hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority); - ok(hres == E_NOINTERFACE, - "QueryInterface(IInternetPriority) returned %08x, expected E_NOINTEFACE\n", hres); - - protocol_start(protocol, blank_url); - hres = IInternetProtocol_LockRequest(protocol, 0); - ok(hres == S_OK, "LockRequest failed: %08x\n", hres); - hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb); - ok(hres == S_OK, "Read failed: %08x\n", hres); - ok(cb == sizeof(blank_html), "cb=%d\n", cb); - ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n"); - hres = IInternetProtocol_UnlockRequest(protocol); - ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres); - - protocol_start(protocol, test_url); - hres = IInternetProtocol_LockRequest(protocol, 0); - ok(hres == S_OK, "LockRequest failed: %08x\n", hres); - hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb); - ok(hres == S_OK, "Read failed: %08x\n", hres); - ok(cb == sizeof(test_html), "cb=%d\n", cb); - ok(!memcmp(buf, test_html, cb), "Readed wrong data\n"); - hres = IInternetProtocol_UnlockRequest(protocol); - ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres); - - protocol_start(protocol, res_url); - hres = IInternetProtocol_LockRequest(protocol, 0); - ok(hres == S_OK, "LockRequest failed: %08x\n", hres); - hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb); - ok(hres == S_OK, "Read failed: %08x\n", hres); - ok(cb == sizeof(blank_html), "cb=%d\n", cb); - ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n"); - hres = IInternetProtocol_UnlockRequest(protocol); - ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres); - - IInternetProtocol_Release(protocol); - } + do_test_about_protocol(factory, 0); + do_test_about_protocol(factory, + BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE); IClassFactory_Release(factory); } diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 5b940c6957c..2efcbbbe0cc 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -2240,6 +2240,7 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type, DWORD *size) { LPSTR data = NULL; + if (value[0]=='#' && value[1]!='#' && value[1]!='%') { if (value[1]=='x') @@ -2321,6 +2322,7 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type, { static const WCHAR szMulti[] = {'[','~',']',0}; LPCWSTR ptr; + LPWSTR newdata; *type=REG_SZ; if (value[0]=='#') @@ -2339,7 +2341,29 @@ static LPSTR parse_value(MSIPACKAGE *package, LPCWSTR value, DWORD *type, if (strstrW(value,szMulti)) *type = REG_MULTI_SZ; + /* remove initial delimiter */ + if (!strncmpW(value, szMulti, 3)) + ptr = value + 3; + *size = deformat_string(package, ptr,(LPWSTR*)&data); + + /* add double NULL terminator */ + if (*type == REG_MULTI_SZ) + { + *size += sizeof(WCHAR); + newdata = msi_alloc(*size); + if (!newdata) + { + msi_free(data); + return NULL; + } + + memcpy(newdata, data, *size - 1); + newdata[*size] = '\0'; + + msi_free(data); + data = (LPSTR)newdata; + } } return data; } diff --git a/dlls/msi/database.c b/dlls/msi/database.c index f3022f44671..64ee1a5e055 100644 --- a/dlls/msi/database.c +++ b/dlls/msi/database.c @@ -408,6 +408,10 @@ static LPWSTR msi_build_createsql_columns(LPWSTR *columns_data, LPWSTR *types, D else type = type_long; break; + default: + ERR("Unknown type: %c\n", types[i][0]); + msi_free(columns); + return NULL; } sprintfW(expanded, column_fmt, columns_data[i], type, size, extra, comma); diff --git a/dlls/msi/format.c b/dlls/msi/format.c dissimilarity index 62% index f56702d35f3..128f159da4a 100644 --- a/dlls/msi/format.c +++ b/dlls/msi/format.c @@ -1,787 +1,1035 @@ -/* - * Implementation of the Microsoft Installer (msi.dll) - * - * Copyright 2005 Mike McCormack for CodeWeavers - * Copyright 2005 Aric Stewart 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 - */ - -/* -http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/msiformatrecord.asp - */ - -#include -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "wine/debug.h" -#include "msi.h" -#include "winnls.h" -#include "objbase.h" -#include "oleauto.h" - -#include "msipriv.h" -#include "msiserver.h" -#include "wine/unicode.h" - -WINE_DEFAULT_DEBUG_CHANNEL(msi); - - -static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, - WCHAR** data, DWORD len, MSIRECORD* record, - BOOL* in_group); - - -static LPWSTR build_default_format(const MSIRECORD* record) -{ - int i; - int count; - LPWSTR rc, buf; - static const WCHAR fmt[] = {'%','i',':',' ','%','s',' ',0}; - static const WCHAR fmt_null[] = {'%','i',':',' ',' ',0}; - static const WCHAR fmt_index[] = {'%','i',0}; - LPCWSTR str; - WCHAR index[10]; - DWORD size, max_len, len; - - count = MSI_RecordGetFieldCount(record); - - max_len = MAX_PATH; - buf = msi_alloc((max_len + 1) * sizeof(WCHAR)); - - rc = NULL; - size = 1; - for (i = 1; i <= count; i++) - { - sprintfW(index,fmt_index,i); - str = MSI_RecordGetString(record, i); - len = (str) ? lstrlenW(str) : 0; - len += (sizeof(fmt_null) - 3) + lstrlenW(index); - size += len; - - if (len > max_len) - { - max_len = len; - buf = msi_realloc(buf, (max_len + 1) * sizeof(WCHAR)); - if (!buf) return NULL; - } - - if (str) - sprintfW(buf,fmt,i,str); - else - sprintfW(buf,fmt_null,i); - - if (!rc) - { - rc = msi_alloc(size * sizeof(WCHAR)); - lstrcpyW(rc, buf); - } - else - { - rc = msi_realloc(rc, size * sizeof(WCHAR)); - lstrcatW(rc, buf); - } - } - msi_free(buf); - return rc; -} - -static const WCHAR* scanW(LPCWSTR buf, WCHAR token, DWORD len) -{ - DWORD i; - for (i = 0; i < len; i++) - if (buf[i] == token) - return &buf[i]; - return NULL; -} - -/* break out helper functions for deformating */ -static LPWSTR deformat_component(MSIPACKAGE* package, LPCWSTR key, DWORD* sz) -{ - LPWSTR value = NULL; - MSICOMPONENT *comp; - BOOL source; - - *sz = 0; - if (!package) - return NULL; - - comp = get_loaded_component(package,key); - if (comp) - { - source = (comp->Action == INSTALLSTATE_SOURCE) ? TRUE : FALSE; - value = resolve_folder(package, comp->Directory, source, FALSE, TRUE, NULL); - *sz = (strlenW(value)) * sizeof(WCHAR); - } - - return value; -} - -static LPWSTR deformat_file(MSIPACKAGE* package, LPCWSTR key, DWORD* sz, - BOOL shortname) -{ - LPWSTR value = NULL; - MSIFILE *file; - - *sz = 0; - - if (!package) - return NULL; - - file = get_loaded_file( package, key ); - if (file) - { - if (!shortname) - { - value = strdupW( file->TargetPath ); - *sz = (strlenW(value)) * sizeof(WCHAR); - } - else - { - DWORD size = 0; - size = GetShortPathNameW( file->TargetPath, NULL, 0 ); - - if (size > 0) - { - *sz = (size-1) * sizeof (WCHAR); - size ++; - value = msi_alloc(size * sizeof(WCHAR)); - GetShortPathNameW( file->TargetPath, value, size ); - } - else - { - value = strdupW( file->TargetPath ); - *sz = (lstrlenW(value)) * sizeof(WCHAR); - } - } - } - - return value; -} - -static LPWSTR deformat_environment(MSIPACKAGE* package, LPCWSTR key, - DWORD* chunk) -{ - LPWSTR value = NULL; - DWORD sz; - - sz = GetEnvironmentVariableW(key,NULL,0); - if (sz > 0) - { - sz++; - value = msi_alloc(sz * sizeof(WCHAR)); - GetEnvironmentVariableW(key,value,sz); - *chunk = (strlenW(value)) * sizeof(WCHAR); - } - else - { - WARN("Unknown environment variable %s\n", debugstr_w(key)); - *chunk = 0; - value = NULL; - } - return value; -} - - -static LPWSTR deformat_NULL(DWORD* chunk) -{ - LPWSTR value; - - value = msi_alloc(sizeof(WCHAR)*2); - value[0] = 0; - *chunk = sizeof(WCHAR); - return value; -} - -static LPWSTR deformat_escape(LPCWSTR key, DWORD* chunk) -{ - LPWSTR value; - - value = msi_alloc(sizeof(WCHAR)*2); - value[0] = key[0]; - *chunk = sizeof(WCHAR); - - return value; -} - - -static BOOL is_key_number(LPCWSTR key) -{ - INT index = 0; - if (key[0] == 0) - return FALSE; - - while (isdigitW(key[index])) index++; - if (key[index] == 0) - return TRUE; - else - return FALSE; -} - -static LPWSTR deformat_index(MSIRECORD* record, LPCWSTR key, DWORD* chunk ) -{ - INT index; - LPWSTR value; - - index = atoiW(key); - TRACE("record index %i\n",index); - value = msi_dup_record_field(record,index); - if (value) - *chunk = strlenW(value) * sizeof(WCHAR); - else - { - value = NULL; - *chunk = 0; - } - return value; -} - -static LPWSTR deformat_property(MSIPACKAGE* package, LPCWSTR key, DWORD* chunk) -{ - LPWSTR value; - - if (!package) - return NULL; - - value = msi_dup_property( package, key ); - - if (value) - *chunk = (strlenW(value)) * sizeof(WCHAR); - - return value; -} - -/* - * Groups cannot be nested. They are just treated as from { to next } - */ -static BOOL find_next_group(LPCWSTR source, DWORD len_remaining, - LPWSTR *group, LPCWSTR *mark, - LPCWSTR* mark2) -{ - int i; - BOOL found = FALSE; - - *mark = scanW(source,'{',len_remaining); - if (!*mark) - return FALSE; - - for (i = 1; (*mark - source) + i < len_remaining; i++) - { - if ((*mark)[i] == '}') - { - found = TRUE; - break; - } - } - if (! found) - return FALSE; - - *mark2 = &(*mark)[i]; - - i = *mark2 - *mark; - *group = msi_alloc(i*sizeof(WCHAR)); - - i -= 1; - memcpy(*group,&(*mark)[1],i*sizeof(WCHAR)); - (*group)[i] = 0; - - TRACE("Found group %s\n",debugstr_w(*group)); - return TRUE; -} - - -static BOOL find_next_outermost_key(LPCWSTR source, DWORD len_remaining, - LPWSTR *key, LPCWSTR *mark, LPCWSTR* mark2, - BOOL *nested) -{ - INT count = 0; - INT total_count = 0; - int i; - - *nested = FALSE; - *mark = scanW(source,'[',len_remaining); - if (!*mark) - return FALSE; - - count = 1; - total_count = 1; - for (i = 1; (*mark - source) + i < len_remaining && count > 0; i++) - { - if ((*mark)[i] == '[' && (*mark)[i-1] != '\\') - { - count ++; - total_count ++; - *nested = TRUE; - } - else if ((*mark)[i] == ']' && (*mark)[i-1] != '\\') - { - count --; - } - } - - if (count > 0) - return FALSE; - - *mark2 = &(*mark)[i-1]; - - i = *mark2 - *mark; - *key = msi_alloc(i*sizeof(WCHAR)); - /* do not have the [] in the key */ - i -= 1; - memcpy(*key,&(*mark)[1],i*sizeof(WCHAR)); - (*key)[i] = 0; - - TRACE("Found Key %s\n",debugstr_w(*key)); - return TRUE; -} - -static LPWSTR deformat_group(MSIPACKAGE* package, LPWSTR group, DWORD len, - MSIRECORD* record, DWORD* size) -{ - LPWSTR value = NULL; - LPCWSTR mark, mark2; - LPWSTR key; - BOOL nested; - INT failcount; - static const WCHAR fmt[] = {'{','%','s','}',0}; - UINT sz; - - if (!group || group[0] == 0) - { - *size = 0; - return NULL; - } - /* if no [] then group is returned as is */ - - if (!find_next_outermost_key(group, len, &key, &mark, &mark2, &nested)) - { - *size = (len+2)*sizeof(WCHAR); - value = msi_alloc(*size); - sprintfW(value,fmt,group); - /* do not return size of the null at the end */ - *size = (len+1)*sizeof(WCHAR); - return value; - } - - msi_free(key); - failcount = 0; - sz = deformat_string_internal(package, group, &value, strlenW(group), - record, &failcount); - if (failcount==0) - { - *size = sz * sizeof(WCHAR); - return value; - } - else if (failcount < 0) - { - LPWSTR v2; - - v2 = msi_alloc((sz+2)*sizeof(WCHAR)); - v2[0] = '{'; - memcpy(&v2[1],value,sz*sizeof(WCHAR)); - v2[sz+1]='}'; - msi_free(value); - - *size = (sz+2)*sizeof(WCHAR); - return v2; - } - else - { - msi_free(value); - *size = 0; - return NULL; - } -} - - -/* - * len is in WCHARs - * return is also in WCHARs - */ -static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, - WCHAR** data, DWORD len, MSIRECORD* record, - INT* failcount) -{ - LPCWSTR mark = NULL; - LPCWSTR mark2 = NULL; - DWORD size=0; - DWORD chunk=0; - LPWSTR key; - LPWSTR value = NULL; - DWORD sz; - LPBYTE newdata = NULL; - const WCHAR* progress = NULL; - BOOL nested = FALSE; - - if (ptr==NULL) - { - TRACE("Deformatting NULL string\n"); - *data = NULL; - return 0; - } - - TRACE("Starting with %s\n",debugstr_wn(ptr,len)); - - /* scan for special characters... fast exit */ - if ((!scanW(ptr,'[',len) || (scanW(ptr,'[',len) && !scanW(ptr,']',len))) && - (scanW(ptr,'{',len) && !scanW(ptr,'}',len))) - { - /* not formatted */ - *data = msi_alloc((len*sizeof(WCHAR))); - memcpy(*data,ptr,len*sizeof(WCHAR)); - TRACE("Returning %s\n",debugstr_wn(*data,len)); - return len; - } - - progress = ptr; - - while (progress - ptr < len) - { - /* seek out first group if existing */ - if (find_next_group(progress, len - (progress - ptr), &key, - &mark, &mark2)) - { - value = deformat_group(package, key, strlenW(key)+1, record, - &chunk); - msi_free( key ); - key = NULL; - nested = FALSE; - } - /* formatted string located */ - else if (!find_next_outermost_key(progress, len - (progress - ptr), - &key, &mark, &mark2, &nested)) - { - LPBYTE nd2; - - TRACE("after value %s\n", debugstr_wn((LPWSTR)newdata, - size/sizeof(WCHAR))); - chunk = (len - (progress - ptr)) * sizeof(WCHAR); - TRACE("after chunk is %i + %i\n",size,chunk); - if (size) - nd2 = msi_realloc(newdata,(size+chunk)); - else - nd2 = msi_alloc(chunk); - - newdata = nd2; - memcpy(&newdata[size],progress,chunk); - size+=chunk; - break; - } - - if (mark != progress) - { - LPBYTE tgt; - DWORD old_size = size; - INT cnt = (mark - progress); - TRACE("%i (%i) characters before marker\n",cnt,(mark-progress)); - size += cnt * sizeof(WCHAR); - if (!old_size) - tgt = msi_alloc(size); - else - tgt = msi_realloc(newdata,size); - newdata = tgt; - memcpy(&newdata[old_size],progress,(cnt * sizeof(WCHAR))); - } - - progress = mark; - - if (nested) - { - TRACE("Nested key... %s\n",debugstr_w(key)); - deformat_string_internal(package, key, &value, strlenW(key)+1, - record, failcount); - - msi_free(key); - key = value; - } - - TRACE("Current %s .. %s\n",debugstr_wn((LPWSTR)newdata, - size/sizeof(WCHAR)),debugstr_w(key)); - - if (!package) - { - /* only deformat number indexs */ - if (key && is_key_number(key)) - { - value = deformat_index(record,key,&chunk); - if (!chunk && failcount && *failcount >= 0) - (*failcount)++; - } - else - { - if (failcount) - *failcount = -1; - if(key) - { - DWORD keylen = strlenW(key); - chunk = (keylen + 2)*sizeof(WCHAR); - value = msi_alloc(chunk); - value[0] = '['; - memcpy(&value[1],key,keylen*sizeof(WCHAR)); - value[1+keylen] = ']'; - } - } - } - else - { - sz = 0; - if (key) switch (key[0]) - { - case '~': - value = deformat_NULL(&chunk); - break; - case '$': - value = deformat_component(package,&key[1],&chunk); - break; - case '#': - value = deformat_file(package,&key[1], &chunk, FALSE); - break; - case '!': /* should be short path */ - value = deformat_file(package,&key[1], &chunk, TRUE); - break; - case '\\': - value = deformat_escape(&key[1],&chunk); - break; - case '%': - value = deformat_environment(package,&key[1],&chunk); - break; - default: - /* index keys cannot be nested */ - if (is_key_number(key)) - if (!nested) - value = deformat_index(record,key,&chunk); - else - { - static const WCHAR fmt[] = {'[','%','s',']',0}; - value = msi_alloc(10); - sprintfW(value,fmt,key); - chunk = strlenW(value)*sizeof(WCHAR); - } - else - value = deformat_property(package,key,&chunk); - break; - } - } - - msi_free(key); - - if (value!=NULL) - { - LPBYTE nd2; - TRACE("value %s, chunk %i size %i\n",debugstr_w(value), - chunk, size); - if (size) - nd2= msi_realloc(newdata,(size + chunk)); - else - nd2= msi_alloc(chunk); - newdata = nd2; - memcpy(&newdata[size],value,chunk); - size+=chunk; - msi_free(value); - } - else if (failcount && *failcount >=0 ) - (*failcount)++; - - progress = mark2+1; - } - - TRACE("after everything %s\n",debugstr_wn((LPWSTR)newdata, - size/sizeof(WCHAR))); - - *data = (LPWSTR)newdata; - return size / sizeof(WCHAR); -} - - -UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer, - LPDWORD size ) -{ - LPWSTR deformated; - LPWSTR rec; - DWORD len; - UINT rc = ERROR_INVALID_PARAMETER; - - TRACE("%p %p %p %i\n", package, record ,buffer, *size); - - rec = msi_dup_record_field(record,0); - if (!rec) - rec = build_default_format(record); - - TRACE("(%s)\n",debugstr_w(rec)); - - len = deformat_string_internal(package,rec,&deformated, - rec ? strlenW(rec) : 0, record, NULL); - - if (buffer) - { - if (*size>len) - { - memcpy(buffer,deformated,len*sizeof(WCHAR)); - rc = ERROR_SUCCESS; - buffer[len] = 0; - } - else - { - if (*size > 0) - { - memcpy(buffer,deformated,(*size)*sizeof(WCHAR)); - buffer[(*size)-1] = 0; - } - rc = ERROR_MORE_DATA; - } - } - else - rc = ERROR_SUCCESS; - - *size = len; - - msi_free(rec); - msi_free(deformated); - return rc; -} - -UINT WINAPI MsiFormatRecordW( MSIHANDLE hInstall, MSIHANDLE hRecord, - LPWSTR szResult, LPDWORD sz ) -{ - UINT r = ERROR_INVALID_HANDLE; - MSIPACKAGE *package; - MSIRECORD *record; - - TRACE("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz); - - package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); - if (!package) - { - HRESULT hr; - IWineMsiRemotePackage *remote_package; - BSTR value = NULL; - DWORD len; - awstring wstr; - - remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); - if (remote_package) - { - len = 0; - hr = IWineMsiRemotePackage_FormatRecord( remote_package, hRecord, - NULL, &len ); - if (FAILED(hr)) - goto done; - - len++; - value = SysAllocStringLen( NULL, len ); - if (!value) - { - r = ERROR_OUTOFMEMORY; - goto done; - } - - hr = IWineMsiRemotePackage_FormatRecord( remote_package, hRecord, - value, &len ); - if (FAILED(hr)) - goto done; - - wstr.unicode = TRUE; - wstr.str.w = szResult; - r = msi_strcpy_to_awstring( value, &wstr, sz ); - -done: - IWineMsiRemotePackage_Release( remote_package ); - SysFreeString( value ); - - if (FAILED(hr)) - { - if (HRESULT_FACILITY(hr) == FACILITY_WIN32) - return HRESULT_CODE(hr); - - return ERROR_FUNCTION_FAILED; - } - - return r; - } - } - - record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); - - if (!record) - return ERROR_INVALID_HANDLE; - if (!sz) - { - msiobj_release( &record->hdr ); - if (szResult) - return ERROR_INVALID_PARAMETER; - else - return ERROR_SUCCESS; - } - - r = MSI_FormatRecordW( package, record, szResult, sz ); - msiobj_release( &record->hdr ); - if (package) - msiobj_release( &package->hdr ); - return r; -} - -UINT WINAPI MsiFormatRecordA( MSIHANDLE hInstall, MSIHANDLE hRecord, - LPSTR szResult, LPDWORD sz ) -{ - UINT r; - DWORD len, save; - LPWSTR value; - - TRACE("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz); - - if (!hRecord) - return ERROR_INVALID_HANDLE; - - if (!sz) - { - if (szResult) - return ERROR_INVALID_PARAMETER; - else - return ERROR_SUCCESS; - } - - r = MsiFormatRecordW( hInstall, hRecord, NULL, &len ); - if (r != ERROR_SUCCESS) - return r; - - value = msi_alloc(++len * sizeof(WCHAR)); - if (!value) - return ERROR_OUTOFMEMORY; - - r = MsiFormatRecordW( hInstall, hRecord, value, &len ); - if (r != ERROR_SUCCESS) - goto done; - - save = len + 1; - len = WideCharToMultiByte(CP_ACP, 0, value, -1, NULL, 0, NULL, NULL); - WideCharToMultiByte(CP_ACP, 0, value, -1, szResult, *sz, NULL, NULL); - - if (szResult && len > *sz) - { - if (*sz) szResult[*sz - 1] = '\0'; - r = ERROR_MORE_DATA; - } - - *sz = save - 1; - -done: - msi_free(value); - return r; -} +/* + * Implementation of the Microsoft Installer (msi.dll) + * + * Copyright 2005 Mike McCormack for CodeWeavers + * Copyright 2005 Aric Stewart 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 +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "wine/debug.h" +#include "msi.h" +#include "winnls.h" +#include "objbase.h" +#include "oleauto.h" + +#include "msipriv.h" +#include "msiserver.h" +#include "wine/unicode.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msi); + +/* types arranged by precedence */ +#define FORMAT_NULL 0x0001 +#define FORMAT_LITERAL 0x0002 +#define FORMAT_NUMBER 0x0004 +#define FORMAT_LBRACK 0x0010 +#define FORMAT_LBRACE 0x0020 +#define FORMAT_RBRACK 0x0011 +#define FORMAT_RBRACE 0x0021 +#define FORMAT_ESCAPE 0x0040 +#define FORMAT_PROPNULL 0x0080 +#define FORMAT_ERROR 0x1000 +#define FORMAT_FAIL 0x2000 + +#define left_type(x) (x & 0xF0) + +typedef struct _tagFORMAT +{ + MSIPACKAGE *package; + MSIRECORD *record; + LPWSTR deformatted; + int len; + int n; + BOOL propfailed; + BOOL groupfailed; + int groups; +} FORMAT; + +typedef struct _tagFORMSTR +{ + struct list entry; + int n; + int len; + int type; + BOOL propfound; + BOOL nonprop; +} FORMSTR; + +typedef struct _tagSTACK +{ + struct list items; +} STACK; + +static STACK *create_stack(void) +{ + STACK *stack = msi_alloc(sizeof(STACK)); + list_init(&stack->items); + return stack; +} + +static void free_stack(STACK *stack) +{ + while (!list_empty(&stack->items)) + { + FORMSTR *str = LIST_ENTRY(list_head(&stack->items), FORMSTR, entry); + list_remove(&str->entry); + msi_free(str); + } + + msi_free(stack); +} + +static void stack_push(STACK *stack, FORMSTR *str) +{ + list_add_head(&stack->items, &str->entry); +} + +static FORMSTR *stack_pop(STACK *stack) +{ + FORMSTR *ret; + + if (list_empty(&stack->items)) + return NULL; + + ret = LIST_ENTRY(list_head(&stack->items), FORMSTR, entry); + list_remove(&ret->entry); + return ret; +} + +static FORMSTR *stack_find(STACK *stack, int type) +{ + FORMSTR *str; + + LIST_FOR_EACH_ENTRY(str, &stack->items, FORMSTR, entry) + { + if (str->type == type) + return str; + } + + return NULL; +} + +static FORMSTR *stack_peek(STACK *stack) +{ + return LIST_ENTRY(list_head(&stack->items), FORMSTR, entry); +} + +static LPCWSTR get_formstr_data(FORMAT *format, FORMSTR *str) +{ + return &format->deformatted[str->n]; +} + +static LPWSTR dup_formstr(FORMAT *format, FORMSTR *str) +{ + LPWSTR val; + LPCWSTR data; + + if (str->len == 0) + return NULL; + + val = msi_alloc((str->len + 1) * sizeof(WCHAR)); + data = get_formstr_data(format, str); + lstrcpynW(val, data, str->len + 1); + + return val; +} + +static LPWSTR deformat_index(FORMAT *format, FORMSTR *str) +{ + LPWSTR val, ret; + + val = msi_alloc((str->len + 1) * sizeof(WCHAR)); + lstrcpynW(val, get_formstr_data(format, str), str->len + 1); + + ret = msi_dup_record_field(format->record, atoiW(val)); + + msi_free(val); + return ret; +} + +static LPWSTR deformat_property(FORMAT *format, FORMSTR *str) +{ + LPWSTR val, ret; + + val = msi_alloc((str->len + 1) * sizeof(WCHAR)); + lstrcpynW(val, get_formstr_data(format, str), str->len + 1); + + ret = msi_dup_property(format->package, val); + + msi_free(val); + return ret; +} + +static LPWSTR deformat_component(FORMAT *format, FORMSTR *str) +{ + LPWSTR key, ret = NULL; + MSICOMPONENT *comp; + BOOL source; + + key = msi_alloc((str->len + 1) * sizeof(WCHAR)); + lstrcpynW(key, get_formstr_data(format, str), str->len + 1); + + comp = get_loaded_component(format->package, key); + if (!comp) + goto done; + + source = (comp->Action == INSTALLSTATE_SOURCE) ? TRUE : FALSE; + ret = resolve_folder(format->package, comp->Directory, source, FALSE, TRUE, NULL); + +done: + msi_free(key); + return ret; +} + +static LPWSTR deformat_file(FORMAT *format, FORMSTR *str, BOOL shortname) +{ + LPWSTR key, ret = NULL; + MSIFILE *file; + DWORD size; + + key = msi_alloc((str->len + 1) * sizeof(WCHAR)); + lstrcpynW(key, get_formstr_data(format, str), str->len + 1); + + file = get_loaded_file(format->package, key); + if (!file) + goto done; + + if (!shortname) + { + ret = strdupW(file->TargetPath); + goto done; + } + + size = GetShortPathNameW(file->TargetPath, NULL, 0); + if (size <= 0) + { + ret = strdupW(file->TargetPath); + goto done; + } + + size++; + ret = msi_alloc(size * sizeof(WCHAR)); + GetShortPathNameW(file->TargetPath, ret, size); + +done: + msi_free(key); + return ret; +} + +static LPWSTR deformat_environment(FORMAT *format, FORMSTR *str) +{ + LPWSTR key, ret = NULL; + DWORD sz; + + key = msi_alloc((str->len + 1) * sizeof(WCHAR)); + lstrcpynW(key, get_formstr_data(format, str), str->len + 1); + + sz = GetEnvironmentVariableW(key, NULL ,0); + if (sz <= 0) + goto done; + + sz++; + ret = msi_alloc(sz * sizeof(WCHAR)); + GetEnvironmentVariableW(key, ret, sz); + +done: + msi_free(key); + return ret; +} + +static LPWSTR deformat_literal(FORMAT *format, FORMSTR *str, BOOL *propfound, + BOOL *nonprop, int *type) +{ + LPCWSTR data = get_formstr_data(format, str); + LPWSTR replaced = NULL; + char ch = data[0]; + + if (ch == '\\') + { + str->n++; + if (str->len == 1) + { + str->len = 0; + replaced = NULL; + } + else + { + str->len = 1; + replaced = dup_formstr(format, str); + } + } + else if (ch == '~') + { + if (str->len != 1) + replaced = NULL; + else + { + replaced = msi_alloc(sizeof(WCHAR)); + *replaced = '\0'; + } + } + else if (ch == '%' || ch == '#' || ch == '!' || ch == '$') + { + str->n++; + str->len--; + + switch (ch) + { + case '%': + replaced = deformat_environment(format, str); break; + case '#': + replaced = deformat_file(format, str, FALSE); break; + case '!': + replaced = deformat_file(format, str, TRUE); break; + case '$': + replaced = deformat_component(format, str); break; + } + + *type = FORMAT_LITERAL; + } + else + { + replaced = deformat_property(format, str); + *type = FORMAT_LITERAL; + + if (replaced) + *propfound = TRUE; + else + format->propfailed = TRUE; + } + + return replaced; +} + +static LPWSTR build_default_format(const MSIRECORD* record) +{ + int i; + int count; + LPWSTR rc, buf; + static const WCHAR fmt[] = {'%','i',':',' ','%','s',' ',0}; + static const WCHAR fmt_null[] = {'%','i',':',' ',' ',0}; + static const WCHAR fmt_index[] = {'%','i',0}; + LPCWSTR str; + WCHAR index[10]; + DWORD size, max_len, len; + + count = MSI_RecordGetFieldCount(record); + + max_len = MAX_PATH; + buf = msi_alloc((max_len + 1) * sizeof(WCHAR)); + + rc = NULL; + size = 1; + for (i = 1; i <= count; i++) + { + sprintfW(index, fmt_index, i); + str = MSI_RecordGetString(record, i); + len = (str) ? lstrlenW(str) : 0; + len += (sizeof(fmt_null) - 3) + lstrlenW(index); + size += len; + + if (len > max_len) + { + max_len = len; + buf = msi_realloc(buf, (max_len + 1) * sizeof(WCHAR)); + if (!buf) return NULL; + } + + if (str) + sprintfW(buf, fmt, i, str); + else + sprintfW(buf, fmt_null, i); + + if (!rc) + { + rc = msi_alloc(size * sizeof(WCHAR)); + lstrcpyW(rc, buf); + } + else + { + rc = msi_realloc(rc, size * sizeof(WCHAR)); + lstrcatW(rc, buf); + } + } + + msi_free(buf); + return rc; +} + +static BOOL format_is_number(WCHAR x) +{ + return ((x >= '0') && (x <= '9')); +} + +static BOOL format_str_is_number(LPWSTR str) +{ + LPWSTR ptr; + + for (ptr = str; *ptr; ptr++) + if (!format_is_number(*ptr)) + return FALSE; + + return TRUE; +} + +static BOOL format_is_alpha(WCHAR x) +{ + return (!format_is_number(x) && x != '\0' && + x != '[' && x != ']' && x != '{' && x != '}'); +} + +static BOOL format_is_literal(WCHAR x) +{ + return (format_is_alpha(x) || format_is_number(x)); +} + +static int format_lex(FORMAT *format, FORMSTR **out) +{ + int type, len = 1; + FORMSTR *str; + LPCWSTR data; + WCHAR ch; + + *out = NULL; + + if (!format->deformatted) + return FORMAT_NULL; + + *out = msi_alloc_zero(sizeof(FORMSTR)); + if (!*out) + return FORMAT_FAIL; + + str = *out; + str->n = format->n; + str->len = 1; + data = get_formstr_data(format, str); + + ch = data[0]; + switch (ch) + { + case '{': type = FORMAT_LBRACE; break; + case '}': type = FORMAT_RBRACE; break; + case '[': type = FORMAT_LBRACK; break; + case ']': type = FORMAT_RBRACK; break; + case '~': type = FORMAT_PROPNULL; break; + case '\0': type = FORMAT_NULL; break; + + default: + type = 0; + } + + if (type) + { + str->type = type; + format->n++; + return type; + } + + if (ch == '\\') + { + while (data[len] && data[len] != ']') + len++; + + type = FORMAT_ESCAPE; + } + else if (format_is_alpha(ch)) + { + while (format_is_literal(data[len])) + len++; + + type = FORMAT_LITERAL; + } + else if (format_is_number(ch)) + { + while (format_is_number(data[len])) + len++; + + type = FORMAT_NUMBER; + + if (data[len] != ']') + { + while (format_is_literal(data[len])) + len++; + + type = FORMAT_LITERAL; + } + } + else + { + ERR("Got unknown character %c(%x)\n", ch, ch); + return FORMAT_ERROR; + } + + format->n += len; + str->len = len; + str->type = type; + + return type; +} + +static FORMSTR *format_replace(FORMAT *format, BOOL propfound, BOOL nonprop, + int oldsize, int type, LPWSTR replace) +{ + FORMSTR *ret; + LPWSTR str, ptr; + DWORD size = 0; + int n; + + if (replace) + { + if (!*replace) + size = 1; + else + size = lstrlenW(replace); + } + + size -= oldsize; + size = format->len + size + 1; + + if (size <= 1) + { + msi_free(format->deformatted); + format->deformatted = NULL; + format->len = 0; + return NULL; + } + + str = msi_alloc(size * sizeof(WCHAR)); + if (!str) + return NULL; + + str[0] = '\0'; + memcpy(str, format->deformatted, format->n * sizeof(WCHAR)); + n = format->n; + + if (replace) + { + if (!*replace) + { + str[n] = '\0'; + n++; + } + else + { + lstrcpyW(&str[n], replace); + n += lstrlenW(replace); + } + } + + ptr = &format->deformatted[format->n + oldsize]; + memcpy(&str[n], ptr, (lstrlenW(ptr) + 1) * sizeof(WCHAR)); + + msi_free(format->deformatted); + format->deformatted = str; + format->len = size - 1; + + if (!replace) + return NULL; + + ret = msi_alloc_zero(sizeof(FORMSTR)); + if (!ret) + return NULL; + + ret->len = lstrlenW(replace); + ret->type = type; + ret->n = format->n; + ret->propfound = propfound; + ret->nonprop = nonprop; + + return ret; +} + +static LPWSTR replace_stack_group(FORMAT *format, STACK *values, + BOOL *propfound, BOOL *nonprop, + int *oldsize, int *type) +{ + LPWSTR replaced = NULL; + FORMSTR *content; + FORMSTR *node; + int n; + + *nonprop = FALSE; + *propfound = FALSE; + + node = stack_pop(values); + n = node->n; + *oldsize = node->len; + msi_free(node); + + while ((node = stack_pop(values))) + { + *oldsize += node->len; + + if (node->nonprop) + *nonprop = TRUE; + + if (node->propfound) + *propfound = TRUE; + + msi_free(node); + } + + content = msi_alloc_zero(sizeof(FORMSTR)); + content->n = n; + content->len = *oldsize; + content->type = FORMAT_LITERAL; + + if (!format->groupfailed && (*oldsize == 2 || + (format->propfailed && !*nonprop))) + { + msi_free(content); + return NULL; + } + else if (format->deformatted[content->n + 1] == '{' && + format->deformatted[content->n + content->len - 2] == '}') + { + format->groupfailed = FALSE; + content->len = 0; + } + else if (*propfound && !*nonprop && + !format->groupfailed && format->groups == 0) + { + content->n++; + content->len -= 2; + } + else + { + if (format->groups != 0) + format->groupfailed = TRUE; + + *nonprop = TRUE; + } + + replaced = dup_formstr(format, content); + *type = content->type; + msi_free(content); + + if (format->groups == 0) + format->propfailed = FALSE; + + return replaced; +} + +static LPWSTR replace_stack_prop(FORMAT *format, STACK *values, + BOOL *propfound, BOOL *nonprop, + int *oldsize, int *type) +{ + LPWSTR replaced = NULL; + FORMSTR *content; + FORMSTR *node; + int n; + + *propfound = FALSE; + *nonprop = FALSE; + + node = stack_pop(values); + n = node->n; + *oldsize = node->len; + *type = stack_peek(values)->type; + msi_free(node); + + while ((node = stack_pop(values))) + { + *oldsize += node->len; + + if (*type != FORMAT_ESCAPE && + stack_peek(values) && node->type != *type) + *type = FORMAT_LITERAL; + + msi_free(node); + } + + content = msi_alloc_zero(sizeof(FORMSTR)); + content->n = n + 1; + content->len = *oldsize - 2; + content->type = *type; + + if (*type == FORMAT_NUMBER) + { + replaced = deformat_index(format, content); + if (replaced) + *propfound = TRUE; + else + format->propfailed = TRUE; + + if (replaced) + *type = format_str_is_number(replaced) ? + FORMAT_NUMBER : FORMAT_LITERAL; + } + else if (format->package) + { + replaced = deformat_literal(format, content, propfound, nonprop, type); + } + else + { + *nonprop = TRUE; + content->n--; + content->len += 2; + replaced = dup_formstr(format, content); + } + + msi_free(content); + return replaced; +} + +static UINT replace_stack(FORMAT *format, STACK *stack, STACK *values) +{ + LPWSTR replaced = NULL; + FORMSTR *beg; + FORMSTR *top; + FORMSTR *node; + BOOL propfound = FALSE; + BOOL nonprop = FALSE; + BOOL group = FALSE; + int oldsize = 0; + int type, n; + + node = stack_peek(values); + type = node->type; + n = node->n; + + if (type == FORMAT_LBRACK) + replaced = replace_stack_prop(format, values, &propfound, + &nonprop, &oldsize, &type); + else if (type == FORMAT_LBRACE) + { + replaced = replace_stack_group(format, values, &propfound, + &nonprop, &oldsize, &type); + group = TRUE; + } + + format->n = n; + beg = format_replace(format, propfound, nonprop, oldsize, type, replaced); + if (!beg) + return ERROR_SUCCESS; + + msi_free(replaced); + format->n = beg->n + beg->len; + + if (type == FORMAT_PROPNULL) + format->n++; + + top = stack_peek(stack); + if (top) + { + type = top->type; + + if ((type == FORMAT_LITERAL || type == FORMAT_NUMBER) && + type == beg->type) + { + top->len += beg->len; + + if (group) + top->nonprop = FALSE; + + if (type == FORMAT_LITERAL) + top->nonprop = beg->nonprop; + + if (beg->propfound) + top->propfound = TRUE; + + msi_free(beg); + return ERROR_SUCCESS; + } + } + + stack_push(stack, beg); + return ERROR_SUCCESS; +} + +static BOOL verify_format(LPWSTR data) +{ + int count = 0; + + while (*data) + { + if (*data == '[' && *(data - 1) != '\\') + count++; + else if (*data == ']') + count--; + + data++; + } + + if (count > 0) + return FALSE; + + return TRUE; +} + +static DWORD deformat_string_internal(MSIPACKAGE *package, LPCWSTR ptr, + WCHAR** data, DWORD *len, + MSIRECORD* record, INT* failcount) +{ + FORMAT format; + FORMSTR *str = NULL; + STACK *stack, *temp; + FORMSTR *node; + int type; + + if (!ptr) + { + *data = NULL; + *len = 0; + return ERROR_SUCCESS; + } + + *data = strdupW(ptr); + *len = lstrlenW(ptr); + + ZeroMemory(&format, sizeof(FORMAT)); + format.package = package; + format.record = record; + format.deformatted = *data; + format.len = *len; + + stack = create_stack(); + temp = create_stack(); + + if (!verify_format(*data)) + return ERROR_SUCCESS; + + while ((type = format_lex(&format, &str)) != FORMAT_NULL) + { + if (type == FORMAT_LBRACK || type == FORMAT_LBRACE || + type == FORMAT_LITERAL || type == FORMAT_NUMBER || + type == FORMAT_ESCAPE || type == FORMAT_PROPNULL) + { + if (type == FORMAT_LBRACE) + { + format.propfailed = FALSE; + format.groups++; + } + else if (type == FORMAT_ESCAPE && + !stack_find(stack, FORMAT_LBRACK)) + { + format.n -= str->len - 1; + str->len = 1; + } + + stack_push(stack, str); + } + else if (type == FORMAT_RBRACK || type == FORMAT_RBRACE) + { + if (type == FORMAT_RBRACE) + format.groups--; + + stack_push(stack, str); + + if (stack_find(stack, left_type(type))) + { + do + { + node = stack_pop(stack); + stack_push(temp, node); + } while (node->type != left_type(type)); + + replace_stack(&format, stack, temp); + } + } + } + + *data = format.deformatted; + *len = format.len; + + msi_free(str); + free_stack(stack); + free_stack(temp); + + return ERROR_SUCCESS; +} + +UINT MSI_FormatRecordW( MSIPACKAGE* package, MSIRECORD* record, LPWSTR buffer, + LPDWORD size ) +{ + LPWSTR deformated; + LPWSTR rec; + DWORD len; + UINT rc = ERROR_INVALID_PARAMETER; + + TRACE("%p %p %p %i\n", package, record ,buffer, *size); + + rec = msi_dup_record_field(record,0); + if (!rec) + rec = build_default_format(record); + + TRACE("(%s)\n",debugstr_w(rec)); + + deformat_string_internal(package, rec, &deformated, &len, record, NULL); + if (buffer) + { + if (*size>len) + { + memcpy(buffer,deformated,len*sizeof(WCHAR)); + rc = ERROR_SUCCESS; + buffer[len] = 0; + } + else + { + if (*size > 0) + { + memcpy(buffer,deformated,(*size)*sizeof(WCHAR)); + buffer[(*size)-1] = 0; + } + rc = ERROR_MORE_DATA; + } + } + else + rc = ERROR_SUCCESS; + + *size = len; + + msi_free(rec); + msi_free(deformated); + return rc; +} + +UINT WINAPI MsiFormatRecordW( MSIHANDLE hInstall, MSIHANDLE hRecord, + LPWSTR szResult, LPDWORD sz ) +{ + UINT r = ERROR_INVALID_HANDLE; + MSIPACKAGE *package; + MSIRECORD *record; + + TRACE("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz); + + package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE ); + if (!package) + { + HRESULT hr; + IWineMsiRemotePackage *remote_package; + BSTR value = NULL; + DWORD len; + awstring wstr; + + remote_package = (IWineMsiRemotePackage *)msi_get_remote( hInstall ); + if (remote_package) + { + len = 0; + hr = IWineMsiRemotePackage_FormatRecord( remote_package, hRecord, + NULL, &len ); + if (FAILED(hr)) + goto done; + + len++; + value = SysAllocStringLen( NULL, len ); + if (!value) + { + r = ERROR_OUTOFMEMORY; + goto done; + } + + hr = IWineMsiRemotePackage_FormatRecord( remote_package, hRecord, + value, &len ); + if (FAILED(hr)) + goto done; + + wstr.unicode = TRUE; + wstr.str.w = szResult; + r = msi_strcpy_to_awstring( value, &wstr, sz ); + +done: + IWineMsiRemotePackage_Release( remote_package ); + SysFreeString( value ); + + if (FAILED(hr)) + { + if (HRESULT_FACILITY(hr) == FACILITY_WIN32) + return HRESULT_CODE(hr); + + return ERROR_FUNCTION_FAILED; + } + + return r; + } + } + + record = msihandle2msiinfo( hRecord, MSIHANDLETYPE_RECORD ); + + if (!record) + return ERROR_INVALID_HANDLE; + if (!sz) + { + msiobj_release( &record->hdr ); + if (szResult) + return ERROR_INVALID_PARAMETER; + else + return ERROR_SUCCESS; + } + + r = MSI_FormatRecordW( package, record, szResult, sz ); + msiobj_release( &record->hdr ); + if (package) + msiobj_release( &package->hdr ); + return r; +} + +UINT WINAPI MsiFormatRecordA( MSIHANDLE hInstall, MSIHANDLE hRecord, + LPSTR szResult, LPDWORD sz ) +{ + UINT r; + DWORD len, save; + LPWSTR value; + + TRACE("%ld %ld %p %p\n", hInstall, hRecord, szResult, sz); + + if (!hRecord) + return ERROR_INVALID_HANDLE; + + if (!sz) + { + if (szResult) + return ERROR_INVALID_PARAMETER; + else + return ERROR_SUCCESS; + } + + r = MsiFormatRecordW( hInstall, hRecord, NULL, &len ); + if (r != ERROR_SUCCESS) + return r; + + value = msi_alloc(++len * sizeof(WCHAR)); + if (!value) + return ERROR_OUTOFMEMORY; + + r = MsiFormatRecordW( hInstall, hRecord, value, &len ); + if (r != ERROR_SUCCESS) + goto done; + + save = len + 1; + len = WideCharToMultiByte(CP_ACP, 0, value, len + 1, NULL, 0, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, value, len, szResult, *sz, NULL, NULL); + + if (szResult && len > *sz) + { + if (*sz) szResult[*sz - 1] = '\0'; + r = ERROR_MORE_DATA; + } + + *sz = save - 1; + +done: + msi_free(value); + return r; +} diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index 70a9c983d1e..643f9cceb7d 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -1519,6 +1519,10 @@ UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, LPWSTR szwFilePath = NULL, lpwVersionBuff = NULL, lpwLangBuff = NULL; UINT ret = ERROR_OUTOFMEMORY; + if ((lpVersionBuf && !pcchVersionBuf) || + (lpLangBuf && !pcchLangBuf)) + return ERROR_INVALID_PARAMETER; + if( szFilePath ) { szwFilePath = strdupAtoW( szFilePath ); @@ -1543,12 +1547,12 @@ UINT WINAPI MsiGetFileVersionA(LPCSTR szFilePath, LPSTR lpVersionBuf, ret = MsiGetFileVersionW(szwFilePath, lpwVersionBuff, pcchVersionBuf, lpwLangBuff, pcchLangBuf); - if( lpwVersionBuff ) + if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwVersionBuff ) WideCharToMultiByte(CP_ACP, 0, lpwVersionBuff, -1, - lpVersionBuf, *pcchVersionBuf, NULL, NULL); - if( lpwLangBuff ) + lpVersionBuf, *pcchVersionBuf + 1, NULL, NULL); + if( (ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) && lpwLangBuff ) WideCharToMultiByte(CP_ACP, 0, lpwLangBuff, -1, - lpLangBuf, *pcchLangBuf, NULL, NULL); + lpLangBuf, *pcchLangBuf + 1, NULL, NULL); end: msi_free(szwFilePath); @@ -1569,7 +1573,7 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, '%','d','.','%','d','.','%','d','.','%','d',0}; static const WCHAR szLangFormat[] = {'%','d',0}; UINT ret = 0; - DWORD dwVerLen; + DWORD dwVerLen, gle; LPVOID lpVer = NULL; VS_FIXEDFILEINFO *ffi; UINT puLen; @@ -1579,9 +1583,21 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, lpVersionBuf, pcchVersionBuf?*pcchVersionBuf:0, lpLangBuf, pcchLangBuf?*pcchLangBuf:0); + if ((lpVersionBuf && !pcchVersionBuf) || + (lpLangBuf && !pcchLangBuf)) + return ERROR_INVALID_PARAMETER; + dwVerLen = GetFileVersionInfoSizeW(szFilePath, NULL); if( !dwVerLen ) - return GetLastError(); + { + gle = GetLastError(); + if (gle == ERROR_BAD_PATHNAME) + return ERROR_FILE_NOT_FOUND; + else if (gle == ERROR_RESOURCE_DATA_NOT_FOUND) + return ERROR_FILE_INVALID; + + return gle; + } lpVer = msi_alloc(dwVerLen); if( !lpVer ) @@ -1595,7 +1611,8 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, ret = GetLastError(); goto end; } - if( lpVersionBuf && pcchVersionBuf && *pcchVersionBuf ) + + if (pcchVersionBuf) { if( VerQueryValueW(lpVer, szVersionResource, (LPVOID*)&ffi, &puLen) && (puLen > 0) ) @@ -1603,24 +1620,32 @@ UINT WINAPI MsiGetFileVersionW(LPCWSTR szFilePath, LPWSTR lpVersionBuf, wsprintfW(tmp, szVersionFormat, HIWORD(ffi->dwFileVersionMS), LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS), LOWORD(ffi->dwFileVersionLS)); - lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf); - *pcchVersionBuf = lstrlenW(lpVersionBuf); + if (lpVersionBuf) lstrcpynW(lpVersionBuf, tmp, *pcchVersionBuf); + + if (lstrlenW(tmp) >= *pcchVersionBuf) + ret = ERROR_MORE_DATA; + + *pcchVersionBuf = lstrlenW(tmp); } else { - *lpVersionBuf = 0; + if (lpVersionBuf) *lpVersionBuf = 0; *pcchVersionBuf = 0; } } - if( lpLangBuf && pcchLangBuf && *pcchLangBuf ) + if (pcchLangBuf) { DWORD lang = GetUserDefaultLangID(); FIXME("Retrieve language from file\n"); wsprintfW(tmp, szLangFormat, lang); - lstrcpynW(lpLangBuf, tmp, *pcchLangBuf); - *pcchLangBuf = lstrlenW(lpLangBuf); + if (lpLangBuf) lstrcpynW(lpLangBuf, tmp, *pcchLangBuf); + + if (lstrlenW(tmp) >= *pcchLangBuf) + ret = ERROR_MORE_DATA; + + *pcchLangBuf = lstrlenW(tmp); } end: diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c index 9828b7f355c..995027057a6 100644 --- a/dlls/msi/streams.c +++ b/dlls/msi/streams.c @@ -54,9 +54,9 @@ typedef struct tagMSISTREAMSVIEW UINT row_size; } MSISTREAMSVIEW; -static BOOL add_stream_to_table(MSISTREAMSVIEW *sv, STREAM *stream, int index) +static BOOL streams_set_table_size(MSISTREAMSVIEW *sv, int size) { - if (index >= sv->max_streams) + if (size >= sv->max_streams) { sv->max_streams *= 2; sv->streams = msi_realloc(sv->streams, sv->max_streams * sizeof(STREAM *)); @@ -64,7 +64,6 @@ static BOOL add_stream_to_table(MSISTREAMSVIEW *sv, STREAM *stream, int index) return FALSE; } - sv->streams[index] = stream; return TRUE; } @@ -140,12 +139,6 @@ static UINT STREAMS_get_row( struct tagMSIVIEW *view, UINT row, MSIRECORD **rec static UINT STREAMS_set_row(struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask) { - FIXME("(%p, %d, %p, %d): stub!\n", view, row, rec, mask); - return ERROR_SUCCESS; -} - -static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary) -{ MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; STREAM *stream; IStream *stm; @@ -156,7 +149,10 @@ static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL tem ULONG count; UINT r = ERROR_FUNCTION_FAILED; - TRACE("(%p, %p, %d)\n", view, rec, temporary); + TRACE("(%p, %p)\n", view, rec); + + if (row > sv->num_rows) + return ERROR_FUNCTION_FAILED; r = MSI_RecordGetIStream(rec, 2, &stm); if (r != ERROR_SUCCESS) @@ -201,8 +197,7 @@ static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL tem IStorage_OpenStream(sv->db->storage, name, 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream); - if (!add_stream_to_table(sv, stream, sv->num_rows++)) - goto done; + sv->streams[row] = stream; done: msi_free(name); @@ -213,6 +208,16 @@ done: return r; } +static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary) +{ + MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; + + if (!streams_set_table_size(sv, ++sv->num_rows)) + return ERROR_FUNCTION_FAILED; + + return STREAMS_set_row(view, sv->num_rows - 1, rec, 0); +} + static UINT STREAMS_delete_row(struct tagMSIVIEW *view, UINT row) { FIXME("(%p %d): stub!\n", view, row); @@ -278,6 +283,52 @@ static UINT STREAMS_get_column_info(struct tagMSIVIEW *view, return ERROR_SUCCESS; } +static UINT streams_find_row(MSISTREAMSVIEW *sv, MSIRECORD *rec, UINT *row) +{ + LPCWSTR str; + UINT i, id, data; + + str = MSI_RecordGetString(rec, 1); + msi_string2idW(sv->db->strings, str, &id); + + for (i = 0; i < sv->num_rows; i++) + { + STREAMS_fetch_int(&sv->view, i, 1, &data); + + if (data == id) + { + *row = i; + return ERROR_SUCCESS; + } + } + + return ERROR_FUNCTION_FAILED; +} + +static UINT streams_modify_update(struct tagMSIVIEW *view, MSIRECORD *rec) +{ + MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; + UINT r, row; + + r = streams_find_row(sv, rec, &row); + if (r != ERROR_SUCCESS) + return ERROR_FUNCTION_FAILED; + + return STREAMS_set_row(view, row, rec, 0); +} + +static UINT streams_modify_assign(struct tagMSIVIEW *view, MSIRECORD *rec) +{ + MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view; + UINT r, row; + + r = streams_find_row(sv, rec, &row); + if (r == ERROR_SUCCESS) + return streams_modify_update(view, rec); + + return STREAMS_insert_row(view, rec, FALSE); +} + static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row) { UINT r; @@ -286,15 +337,21 @@ static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRE switch (eModifyMode) { + case MSIMODIFY_ASSIGN: + r = streams_modify_assign(view, rec); + break; + case MSIMODIFY_INSERT: r = STREAMS_insert_row(view, rec, FALSE); break; + case MSIMODIFY_UPDATE: + r = streams_modify_update(view, rec); + break; + case MSIMODIFY_VALIDATE_NEW: case MSIMODIFY_INSERT_TEMPORARY: - case MSIMODIFY_UPDATE: case MSIMODIFY_REFRESH: - case MSIMODIFY_ASSIGN: case MSIMODIFY_REPLACE: case MSIMODIFY_MERGE: case MSIMODIFY_DELETE: @@ -425,11 +482,13 @@ static UINT add_streams_to_table(MSISTREAMSVIEW *sv) STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &stream->stream); CoTaskMemFree(stat.pwcsName); - if (!add_stream_to_table(sv, stream, count++)) + if (!streams_set_table_size(sv, ++count)) { count = -1; break; } + + sv->streams[count - 1] = stream; } IEnumSTATSTG_Release(stgenum); diff --git a/dlls/msi/tests/Makefile.in b/dlls/msi/tests/Makefile.in index 4f17318d371..11c8cd0a9bc 100644 --- a/dlls/msi/tests/Makefile.in +++ b/dlls/msi/tests/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../../.. SRCDIR = @srcdir@ VPATH = @srcdir@ TESTDLL = msi.dll -IMPORTS = cabinet msi shell32 ole32 oleaut32 advapi32 kernel32 +IMPORTS = cabinet msi shell32 ole32 oleaut32 advapi32 kernel32 version EXTRALIBS = -luuid CTESTS = \ diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 85b65d76301..e912a3a0685 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -1590,6 +1590,18 @@ static const CHAR two_primary[] = "PrimaryOne\tPrimaryTwo\n" "papaya\tleaf\n" "papaya\tflower\n"; +static const CHAR endlines1[] = "A\tB\tC\tD\tE\tF\r\n" + "s72\ts72\ts72\ts72\ts72\ts72\n" + "Table\tA\r\n" + "a\tb\tc\td\te\tf\n" + "g\th\ti\t\rj\tk\tl\r\n"; + +static const CHAR endlines2[] = "A\tB\tC\tD\tE\tF\r" + "s72\ts72\ts72\ts72\ts72\ts72\n" + "Table2\tA\r\n" + "a\tb\tc\td\te\tf\n" + "g\th\ti\tj\tk\tl\r\n"; + static void write_file(const CHAR *filename, const char *data, int data_size) { DWORD size; @@ -1630,6 +1642,19 @@ static void test_msiimport(void) r = add_table_to_db(hdb, two_primary); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = add_table_to_db(hdb, endlines1); + todo_wine + { + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + } + + r = add_table_to_db(hdb, endlines2); + todo_wine + { + ok(r == ERROR_FUNCTION_FAILED, + "Expected ERROR_FUNCTION_FAILED, got %d\n", r); + } + query = "SELECT * FROM `TestTable`"; r = MsiDatabaseOpenView(hdb, query, &view); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); @@ -1733,6 +1758,95 @@ static void test_msiimport(void) ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); MsiCloseHandle(view); + + query = "SELECT * FROM `Table`"; + r = MsiDatabaseOpenView(hdb, query, &view); + todo_wine + { + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + } + + r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec); + count = MsiRecordGetFieldCount(rec); + todo_wine + { + ok(count == 6, "Expected 6, got %d\n", count); + ok(check_record(rec, 1, "A"), "Expected A\n"); + ok(check_record(rec, 2, "B"), "Expected B\n"); + ok(check_record(rec, 3, "C"), "Expected C\n"); + ok(check_record(rec, 4, "D"), "Expected D\n"); + ok(check_record(rec, 5, "E"), "Expected E\n"); + ok(check_record(rec, 6, "F"), "Expected F\n"); + } + MsiCloseHandle(rec); + + r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec); + count = MsiRecordGetFieldCount(rec); + todo_wine + { + ok(count == 6, "Expected 6, got %d\n", count); + ok(check_record(rec, 1, "s72"), "Expected s72\n"); + ok(check_record(rec, 2, "s72"), "Expected s72\n"); + ok(check_record(rec, 3, "s72"), "Expected s72\n"); + ok(check_record(rec, 4, "s72"), "Expected s72\n"); + ok(check_record(rec, 5, "s72"), "Expected s72\n"); + ok(check_record(rec, 6, "s72"), "Expected s72\n"); + } + MsiCloseHandle(rec); + + MsiViewClose(view); + MsiCloseHandle(view); + + query = "SELECT * FROM `Table`"; + r = MsiDatabaseOpenView(hdb, query, &view); + todo_wine + { + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + } + + r = MsiViewExecute(view, 0); + todo_wine + { + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + } + + r = MsiViewFetch(view, &rec); + todo_wine + { + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(check_record(rec, 1, "a"), "Expected 'a'\n"); + ok(check_record(rec, 2, "b"), "Expected 'b'\n"); + ok(check_record(rec, 3, "c"), "Expected 'c'\n"); + ok(check_record(rec, 4, "d"), "Expected 'd'\n"); + ok(check_record(rec, 5, "e"), "Expected 'e'\n"); + ok(check_record(rec, 6, "f"), "Expected 'f'\n"); + } + + MsiCloseHandle(rec); + + r = MsiViewFetch(view, &rec); + todo_wine + { + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(check_record(rec, 1, "g"), "Expected 'g'\n"); + ok(check_record(rec, 2, "h"), "Expected 'h'\n"); + ok(check_record(rec, 3, "i"), "Expected 'i'\n"); + ok(check_record(rec, 4, "j"), "Expected 'j'\n"); + ok(check_record(rec, 5, "k"), "Expected 'k'\n"); + ok(check_record(rec, 6, "l"), "Expected 'l'\n"); + } + + MsiCloseHandle(rec); + + r = MsiViewFetch(view, &rec); + todo_wine + { + ok(r == ERROR_NO_MORE_ITEMS, + "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + } + + MsiViewClose(view); + MsiCloseHandle(view); MsiCloseHandle(hdb); DeleteFileA(msifile); } @@ -5053,6 +5167,340 @@ static void test_deleterow() DeleteFileA(msifile); } +static const CHAR import_dat[] = "A\n" + "s72\n" + "Table\tA\n" + "This is a new 'string' ok\n"; + +static void test_quotes(void) +{ + MSIHANDLE hdb, hview, hrec; + const char *query; + char buf[MAX_PATH]; + UINT r; + DWORD size; + + DeleteFile(msifile); + + r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a 'string' ok' )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "INSERT INTO `Table` ( `A` ) VALUES ( \"This is a 'string' ok\" )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "INSERT INTO `Table` ( `A` ) VALUES ( \"test\" )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a ''string'' ok' )"; + r = run_query(hdb, 0, query); + todo_wine + { + ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + } + + query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a '''string''' ok' )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \'string\' ok' )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "INSERT INTO `Table` ( `A` ) VALUES ( 'This is a \"string\" ok' )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "SELECT * FROM `Table`"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + size = MAX_PATH; + r = MsiRecordGetString(hrec, 1, buf, &size); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine + { + ok(!lstrcmp(buf, "This is a \"string\" ok"), + "Expected \"This is a \"string\" ok\", got %s\n", buf); + } + + MsiCloseHandle(hrec); + + r = MsiViewFetch(hview, &hrec); + todo_wine + { + ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + } + + MsiCloseHandle(hview); + + write_file("import.idt", import_dat, (sizeof(import_dat) - 1) * sizeof(char)); + + r = MsiDatabaseImportA(hdb, CURR_DIR, "import.idt"); + todo_wine + { + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + } + + DeleteFileA("import.idt"); + + query = "SELECT * FROM `Table`"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + size = MAX_PATH; + r = MsiRecordGetString(hrec, 1, buf, &size); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine + { + ok(!lstrcmp(buf, "This is a new 'string' ok"), + "Expected \"This is a new 'string' ok\", got %s\n", buf); + } + + MsiCloseHandle(hrec); + + r = MsiViewFetch(hview, &hrec); + todo_wine + { + ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + } + + MsiCloseHandle(hview); + + MsiCloseHandle(hdb); + DeleteFileA(msifile); +} + +static void test_carriagereturn(void) +{ + MSIHANDLE hdb, hview, hrec; + const char *query; + char buf[MAX_PATH]; + UINT r; + DWORD size; + + DeleteFile(msifile); + + r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "CREATE TABLE `Table`\r ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + todo_wine + { + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + } + + query = "CREATE TABLE `Table` \r( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE\r TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE\r `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` (\r `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A`\r CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A` CHAR(72)\r NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT\r NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT \rNULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL\r PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL \rPRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY\r KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY \rKEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY\r `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A`\r )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Table` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )\r"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `\rOne` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "CREATE TABLE `Tw\ro` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "CREATE TABLE `Three\r` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "CREATE TABLE `Four` ( `A\r` CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Four` ( `\rA` CHAR(72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Four` ( `A` CHAR(72\r) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + todo_wine + { + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + } + + query = "CREATE TABLE `Four` ( `A` CHAR(\r72) NOT NULL PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `\rA` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `Four` ( `A` CHAR(72) NOT NULL PRIMARY KEY `A\r` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "SELECT * FROM `_Tables`"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + size = MAX_PATH; + r = MsiRecordGetStringA(hrec, 1, buf, &size); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine + { + ok(!lstrcmpA(buf, "\rOne"), "Expected \"\\rOne\", got \"%s\"\n", buf); + } + + MsiCloseHandle(hrec); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + size = MAX_PATH; + r = MsiRecordGetStringA(hrec, 1, buf, &size); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine + { + ok(!lstrcmpA(buf, "Tw\ro"), "Expected \"Tw\\ro\", got \"%s\"\n", buf); + } + + MsiCloseHandle(hrec); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + size = MAX_PATH; + r = MsiRecordGetStringA(hrec, 1, buf, &size); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine + { + ok(!lstrcmpA(buf, "Three\r"), + "Expected \"Three\r\", got \"%s\"\n", buf); + } + + MsiCloseHandle(hrec); + + r = MsiViewFetch(hview, &hrec); + todo_wine + { + ok(r == ERROR_NO_MORE_ITEMS, + "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + } + + MsiViewClose(hview); + MsiCloseHandle(hview); + + MsiCloseHandle(hdb); + DeleteFileA(msifile); +} + START_TEST(db) { test_msidatabase(); @@ -5084,4 +5532,6 @@ START_TEST(db) test_order(); test_viewmodify_delete_temporary(); test_deleterow(); + test_quotes(); + test_carriagereturn(); } diff --git a/dlls/msi/tests/format.c b/dlls/msi/tests/format.c index 2c9861e96e7..aec347dad73 100644 --- a/dlls/msi/tests/format.c +++ b/dlls/msi/tests/format.c @@ -517,7 +517,6 @@ static void test_formatrecord(void) ok( sz == 7, "size wrong\n"); ok( 0 == strcmp(buffer,"boo hoo"), "wrong output\n"); - /* empty string */ r = MsiRecordSetString(hrec, 0, ""); sz = sizeof buffer; @@ -734,11 +733,8 @@ static void test_formatrecord(void) sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - - todo_wine{ ok( sz == 16, "size wrong,(%i)\n",sz); ok( 0 == strcmp(buffer,"{{2hey}1[dummy]}"), "wrong output (%s)\n",buffer); - } r = MsiRecordSetString(hrec, 0, "{{[1][2]}[3]{[4][dummy]}}"); r = MsiRecordSetString(hrec, 1, "2"); @@ -750,10 +746,8 @@ static void test_formatrecord(void) sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine{ ok( sz == 0, "size wrong,(%i)\n",sz); ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer); - } r = MsiRecordSetString(hrec, 0, "{{[1][2]}[3]} {[1][2]}"); r = MsiRecordSetString(hrec, 1, "1"); @@ -765,10 +759,8 @@ static void test_formatrecord(void) sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine{ ok( sz == 12, "size wrong,(%i)\n",sz); ok( 0 == strcmp(buffer,"{{12}3} {12}"), "wrong output (%s)\n",buffer); - } r = MsiRecordSetString(hrec, 0, "{[1][2]} {{[1][2]}[3]} {[1][2]}"); r = MsiRecordSetString(hrec, 1, "1"); @@ -780,10 +772,8 @@ static void test_formatrecord(void) sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine{ ok( sz == 15, "size wrong,(%i)\n",sz); ok( 0 == strcmp(buffer,"12 {{12}3} {12}"), "wrong output (%s)\n",buffer); - } r = MsiRecordSetString(hrec, 0, "{[4]}{[1][2]} {{[1][2]}[3]} {[1][2]}"); r = MsiRecordSetString(hrec, 1, "1"); @@ -795,11 +785,8 @@ static void test_formatrecord(void) sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine{ ok( sz == 15, "size wrong,(%i)\n",sz); ok( 0 == strcmp(buffer,"12 {{12}3} {12}"), "wrong output (%s)\n",buffer); - } - r = MsiRecordSetString(hrec, 0, "{blah} {[4]}{[1][2]} {{[1][2]}[3]} {[1][2]}"); r = MsiRecordSetString(hrec, 1, "1"); @@ -811,10 +798,8 @@ static void test_formatrecord(void) sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine{ ok( sz == 22, "size wrong,(%i)\n",sz); ok( 0 == strcmp(buffer,"{blah} 12 {{12}3} {12}"), "wrong output (%s)\n",buffer); - } r = MsiRecordSetString(hrec, 0, "{{[1]}[2]} {[4]}{[1][2]}"); r = MsiRecordSetString(hrec, 1, "1"); @@ -826,10 +811,8 @@ static void test_formatrecord(void) sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine{ ok( sz == 13, "size wrong,(%i)\n",sz); ok( 0 == strcmp(buffer,"{{1}2} {}{12}"), "wrong output (%s)\n",buffer); - } r = MsiRecordSetString(hrec, 0, "{{[1]}} {[4]}{[1][2]}"); r = MsiRecordSetString(hrec, 1, "1"); @@ -841,10 +824,8 @@ static void test_formatrecord(void) sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine{ ok( sz == 3, "size wrong,(%i)\n",sz); ok( 0 == strcmp(buffer," 12"), "wrong output (%s)\n",buffer); - } r = MsiRecordSetString(hrec, 0, "{{{[1]}} {[4]}{[1][2]}"); r = MsiRecordSetString(hrec, 1, "1"); @@ -1015,61 +996,54 @@ static void test_formatrecord(void) ok( 0 == strcmp(buffer,"boo hoo"), "wrong output\n"); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{[1]}}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 0, "size wrong\n"); ok( 0 == strcmp(buffer,""), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "{ {[1]}}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( 0 == strcmp(buffer," {hoo}"), "wrong output\n"); - ok( sz == 6, "size wrong\n"); + todo_wine + { + ok( 0 == strcmp(buffer," {hoo}"), "wrong output\n"); + ok( sz == 6, "size wrong\n"); + } ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{[1]} }"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 8, "size wrong\n"); ok( 0 == strcmp(buffer,"{{hoo} }"), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{ [1]}}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 0, "size wrong\n"); ok( 0 == strcmp(buffer,""), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{[1] }}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 0, "size wrong\n"); ok( 0 == strcmp(buffer,""), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{a}{b}{c }{ d}{any text}}"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 0, "size wrong\n"); ok( 0 == strcmp(buffer,""), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "{{a} }"); @@ -1079,13 +1053,11 @@ static void test_formatrecord(void) ok( 0 == strcmp(buffer,"{{a} }"), "wrong output\n"); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{a} {b}}"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 0, "size wrong\n"); ok( 0 == strcmp(buffer,""), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); todo_wine { @@ -1097,13 +1069,11 @@ static void test_formatrecord(void) } ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{a b}}"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 0, "size wrong\n"); ok( 0 == strcmp(buffer,""), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "{ }"); @@ -1113,13 +1083,11 @@ static void test_formatrecord(void) ok( 0 == strcmp(buffer,"{ }"), "wrong output\n"); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, " {{a}}}"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 2, "size wrong\n"); ok( 0 == strcmp(buffer," }"), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); todo_wine { @@ -1174,6 +1142,14 @@ static void test_formatrecord(void) ok( 0 == strcmp(buffer,"[\\[]"), "wrong output\n"); ok( r == ERROR_SUCCESS, "format failed\n"); + MsiRecordSetString(hrec, 0, "[\\[]"); + MsiRecordSetString(hrec, 1, "hoo"); + sz = sizeof(buffer); + r = MsiFormatRecord(0, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 4, "Expected 4, got %d\n", sz); + ok(!lstrcmpA(buffer, "[\\[]"), "Expected \"[\\[]\", got \"%s\"\n", buffer); + r = MsiRecordSetString(hrec, 0, "[foo]"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; @@ -1198,44 +1174,36 @@ static void test_formatrecord(void) ok( 0 == strcmp(buffer,"[%FOO]"), "wrong output\n"); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{[1]}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 6, "size wrong\n"); ok( 0 == strcmp(buffer,"{{hoo}"), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{ {[1]}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 8, "size wrong\n"); ok( 0 == strcmp(buffer,"{{ {hoo}"), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{ {[1]}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 8, "size wrong\n"); ok( 0 == strcmp(buffer,"{{ {hoo}"), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{ {{[1]}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 9, "size wrong\n"); ok( 0 == strcmp(buffer,"{{ {{hoo}"), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "[1]}"); @@ -1264,24 +1232,33 @@ static void test_formatrecord(void) r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 19, "size wrong\n"); - ok( 0 == strcmp(buffer,"01{2{3{4hoo56}7}8}9"), "wrong output\n"); + todo_wine + { + ok( sz == 19, "size wrong\n"); + ok( 0 == strcmp(buffer,"01{2{3{4hoo56}7}8}9"), "wrong output\n"); + } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "0{1{2[1]3}4"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 9, "size wrong\n"); - ok( 0 == strcmp(buffer,"01{2hoo34"), "wrong output\n"); + todo_wine + { + ok( sz == 9, "size wrong\n"); + ok( 0 == strcmp(buffer,"01{2hoo34"), "wrong output\n"); + } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "0{1{2[1]3}4"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 9, "size wrong\n"); - ok( 0 == strcmp(buffer,"01{2hoo34"), "wrong output\n"); + todo_wine + { + ok( sz == 9, "size wrong\n"); + ok( 0 == strcmp(buffer,"01{2hoo34"), "wrong output\n"); + } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "{[1.} [1]"); @@ -1289,7 +1266,10 @@ static void test_formatrecord(void) sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 9, "size wrong\n"); - ok( 0 == strcmp(buffer,"{[1.} hoo"), "wrong output\n"); + todo_wine + { + ok( 0 == strcmp(buffer,"{[1.} hoo"), "wrong output\n"); + } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "{[{[1]}]}"); @@ -1297,8 +1277,11 @@ static void test_formatrecord(void) r = MsiRecordSetString(hrec, 2, "foo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 9, "size wrong\n"); - ok( 0 == strcmp(buffer,"{[{[1]}]}"), "wrong output\n"); + todo_wine + { + ok( sz == 9, "size wrong\n"); + ok( 0 == strcmp(buffer,"{[{[1]}]}"), "wrong output\n"); + } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "{[1][}"); @@ -1306,8 +1289,11 @@ static void test_formatrecord(void) r = MsiRecordSetString(hrec, 2, "foo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 2, "size wrong\n"); - ok( 0 == strcmp(buffer,"2["), "wrong output\n"); + todo_wine + { + ok( sz == 2, "size wrong\n"); + ok( 0 == strcmp(buffer,"2["), "wrong output\n"); + } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "[1]"); @@ -1319,17 +1305,17 @@ static void test_formatrecord(void) ok( 0 == strcmp(buffer,"[2]"), "wrong output\n"); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "[{{boo}}1]"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); + ok( r == ERROR_SUCCESS, "format failed\n"); ok( sz == 3, "size wrong\n"); - ok( 0 == strcmp(buffer,"[1]"), "wrong output\n"); + todo_wine + { + ok( 0 == strcmp(buffer,"[1]"), "wrong output: %s\n", buffer); } - ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "[{{boo}}1]"); r = MsiRecordSetString(hrec, 0, "[1{{boo}}]"); r = MsiRecordSetString(hrec, 1, "hoo"); @@ -1337,33 +1323,36 @@ static void test_formatrecord(void) r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 3, "size wrong\n"); ok( 0 == strcmp(buffer,"[1]"), "wrong output\n"); - } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "{[1]{{boo} }}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 11, "size wrong\n"); - ok( 0 == strcmp(buffer,"hoo{{boo }}"), "wrong output\n"); + todo_wine + { + ok( sz == 11, "size wrong\n"); + ok( 0 == strcmp(buffer,"hoo{{boo }}"), "wrong output\n"); + } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "{[1{{boo}}]}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 12, "size wrong: got %u, expected 12\n", sz); - ok( 0 == strcmp(buffer,"{[1{{boo}}]}"), "wrong output: got %s, expected [1]\n", buffer); + todo_wine + { + ok( sz == 12, "size wrong: got %u, expected 12\n", sz); + ok( 0 == strcmp(buffer,"{[1{{boo}}]}"), "wrong output: got %s, expected [1]\n", buffer); + } ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine { r = MsiRecordSetString(hrec, 0, "{{[1]}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); ok( sz == 6, "size wrong: got %u, expected 3\n", sz); ok( 0 == strcmp(buffer,"{{hoo}"), "wrong output: got %s, expected [1]\n", buffer); - } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "{[1{{bo}o}}]}"); @@ -1377,16 +1366,22 @@ static void test_formatrecord(void) r = MsiRecordSetString(hrec, 0, "{[1{{b{o}o}}]}"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 14, "size wrong\n"); - ok( 0 == strcmp(buffer,"{[1{{b{o}o}}]}"), "wrong output %s\n",buffer); + todo_wine + { + ok( sz == 14, "size wrong\n"); + ok( 0 == strcmp(buffer,"{[1{{b{o}o}}]}"), "wrong output %s\n",buffer); + } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "{ {[1]}"); r = MsiRecordSetString(hrec, 1, "hoo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 5, "size wrong\n"); - ok( 0 == strcmp(buffer," {hoo"), "wrong output %s\n",buffer); + todo_wine + { + ok( sz == 5, "size wrong\n"); + ok( 0 == strcmp(buffer," {hoo"), "wrong output %s\n",buffer); + } ok( r == ERROR_SUCCESS, "format failed\n"); /* {} inside a substitution does strange things... */ @@ -1394,24 +1389,33 @@ static void test_formatrecord(void) r = MsiRecordSetString(hrec, 1, "2"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 5, "size wrong\n"); - ok( 0 == strcmp(buffer,"[[1]]"), "wrong output %s\n",buffer); + todo_wine + { + ok( sz == 5, "size wrong\n"); + ok( 0 == strcmp(buffer,"[[1]]"), "wrong output %s\n",buffer); + } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "[[1]{}[1]]"); r = MsiRecordSetString(hrec, 1, "2"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 6, "size wrong\n"); - ok( 0 == strcmp(buffer,"[[1]2]"), "wrong output %s\n",buffer); + todo_wine + { + ok( sz == 6, "size wrong\n"); + ok( 0 == strcmp(buffer,"[[1]2]"), "wrong output %s\n",buffer); + } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "[a[1]b[1]c{}d[1]e]"); r = MsiRecordSetString(hrec, 1, "2"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 14, "size wrong\n"); - ok( 0 == strcmp(buffer,"[a[1]b[1]cd2e]"), "wrong output %s\n",buffer); + todo_wine + { + ok( sz == 14, "size wrong\n"); + ok( 0 == strcmp(buffer,"[a[1]b[1]cd2e]"), "wrong output %s\n",buffer); + } ok( r == ERROR_SUCCESS, "format failed\n"); r = MsiRecordSetString(hrec, 0, "[a[1]b"); @@ -1489,8 +1493,11 @@ static void test_formatrecord(void) r = MsiRecordSetString(hrec, 1, "foo"); sz = sizeof buffer; r = MsiFormatRecord(0, hrec, buffer, &sz); - ok( sz == 12, "size wrong\n"); - ok( 0 == strcmp(buffer,"{foo[-1]foo}"), "wrong output %s\n",buffer); + todo_wine + { + ok( sz == 12, "size wrong\n"); + ok( 0 == strcmp(buffer,"{foo[-1]foo}"), "wrong output %s\n",buffer); + } ok( r == ERROR_SUCCESS, "format failed\n"); /* nested braces */ @@ -1540,31 +1547,22 @@ static void test_formatrecord(void) MsiRecordSetString(hrec, 0, "{abc}{{def}hi{j[one]k}}"); r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine - { - ok( sz == 5, "size wrong(%i)\n",sz); - ok( 0 == strcmp(buffer,"{abc}"), "wrong output (%s)\n",buffer); - } + ok( sz == 5, "size wrong(%i)\n",sz); + ok( 0 == strcmp(buffer,"{abc}"), "wrong output (%s)\n",buffer); sz = sizeof buffer; MsiRecordSetString(hrec, 0, "{{def}hi{j[one]k}}"); r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine - { - ok( sz == 0, "size wrong(%i)\n",sz); - ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer); - } + ok( sz == 0, "size wrong(%i)\n",sz); + ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer); sz = sizeof buffer; MsiRecordSetString(hrec, 0, "{{def}hi{jk}}"); r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine - { - ok( sz == 0, "size wrong(%i)\n",sz); - ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer); - } + ok( sz == 0, "size wrong(%i)\n",sz); + ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer); sz = sizeof buffer; MsiRecordSetString(hrec, 0, "{{{def}}hi{jk}}"); @@ -1590,21 +1588,15 @@ static void test_formatrecord(void) MsiRecordSetString(hrec, 0, "{{def}{jk}}"); r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine - { - ok( sz == 0, "size wrong(%i)\n",sz); - ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer); - } + ok( sz == 0, "size wrong(%i)\n",sz); + ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer); sz = sizeof buffer; MsiRecordSetString(hrec, 0, "{{def}}"); r = MsiFormatRecord(0, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine - { - ok( sz == 0, "size wrong(%i)\n",sz); - ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer); - } + ok( sz == 0, "size wrong(%i)\n",sz); + ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer); sz = sizeof buffer; MsiRecordSetString(hrec, 0, "{a{b}c}"); @@ -1652,11 +1644,8 @@ static void test_formatrecord(void) r = MsiFormatRecord(0, hrec, buffer, &sz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(sz == 33, "Expected 33, got %d\n",sz); - todo_wine - { - ok(!lstrcmpA(buffer, "one {[noprop] [twoprop]} {abcdef}"), - "Expected \"one {[noprop] [twoprop]} {abcdef}\", got \"%s\"\n", buffer); - } + ok(!lstrcmpA(buffer, "one {[noprop] [twoprop]} {abcdef}"), + "Expected \"one {[noprop] [twoprop]} {abcdef}\", got \"%s\"\n", buffer); sz = sizeof(buffer); MsiRecordSetString(hrec, 0, "[1] {[noprop] [one]} {abcdef}"); @@ -1664,11 +1653,8 @@ static void test_formatrecord(void) r = MsiFormatRecord(0, hrec, buffer, &sz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(sz == 29, "Expected 29, got %d\n",sz); - todo_wine - { - ok(!lstrcmpA(buffer, "one {[noprop] [one]} {abcdef}"), - "Expected \"one {[noprop] [one]} {abcdef}\", got \"%s\"\n", buffer); - } + ok(!lstrcmpA(buffer, "one {[noprop] [one]} {abcdef}"), + "Expected \"one {[noprop] [one]} {abcdef}\", got \"%s\"\n", buffer); sz = sizeof(buffer); MsiRecordSetString(hrec, 0, "[1] {[one]} {abcdef}"); @@ -1676,11 +1662,8 @@ static void test_formatrecord(void) r = MsiFormatRecord(0, hrec, buffer, &sz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(sz == 20, "Expected 20, got %d\n",sz); - todo_wine - { - ok(!lstrcmpA(buffer, "one {[one]} {abcdef}"), - "Expected \"one {[one]} {abcdef}\", got \"%s\"\n", buffer); - } + ok(!lstrcmpA(buffer, "one {[one]} {abcdef}"), + "Expected \"one {[one]} {abcdef}\", got \"%s\"\n", buffer); MsiCloseHandle( hrec ); } @@ -1742,7 +1725,9 @@ static void test_formatrecord_package(void) todo_wine { ok( sz == 66, "size wrong (%i)\n",sz); - ok( 0 == strcmp(buffer,"1: [2] 2: stuff 3: prop 4: val 5: 6: 7: 8: 9: 10: 11: 12: "), "wrong output(%s)\n",buffer); + ok( !lstrcmpA(buffer, + "1: [2] 2: stuff 3: prop 4: val 5: 6: 7: 8: 9: 10: 11: 12: "), + "wrong output(%s)\n",buffer); } /* now put play games with escaping */ @@ -1794,6 +1779,101 @@ static void test_formatrecord_package(void) ok( sz == 0, "size wrong: %d\n", sz); ok( 0 == strcmp(buffer,""), "wrong output: %s\n", buffer); + MsiRecordSetString(hrec, 0, "\\x"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 2, "Expected 2, got %d\n", sz); + ok(!lstrcmpA(buffer, "\\x"), "Expected \"\\x\", got \"%s\"\n", buffer); + + MsiRecordSetString(hrec, 0, "[\\["); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 3, "Expected 3, got %d\n", sz); + ok(!lstrcmpA(buffer, "[\\["), "Expected \"[\\[\", got \"%s\"\n", buffer); + + MsiRecordSetString(hrec, 0, "[\\[]"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 1, "Expected 1, got %d\n", sz); + ok(!lstrcmpA(buffer, "["), "Expected \"[\", got \"%s\"\n", buffer); + + MsiRecordSetString(hrec, 0, "[[]"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 3, "Expected 3, got %d\n", sz); + ok(!lstrcmpA(buffer, "[[]"), "Expected \"[]\", got \"%s\"\n", buffer); + + MsiRecordSetString(hrec, 0, "[\\[]]"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 2, "Expected 2, got %d\n", sz); + ok(!lstrcmpA(buffer, "[]"), "Expected \"[]\", got \"%s\"\n", buffer); + + MsiRecordSetString(hrec, 0, "[\\[a]"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 1, "Expected 1, got %d\n", sz); + ok(!lstrcmpA(buffer, "["), "Expected \"[\", got \"%s\"\n", buffer); + + MsiRecordSetString(hrec, 0, "[\\a[]"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine + { + ok(sz == 1, "Expected 1, got %d\n", sz); + ok(!lstrcmpA(buffer, "a"), "Expected \"a\", got \"%s\"\n", buffer); + } + + MsiRecordSetString(hrec, 0, "[prop]"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 3, "Expected 3, got %d\n", sz); + ok(!lstrcmpA(buffer, "val"), "Expected \"val\", got \"%s\"\n", buffer); + + MsiRecordSetString(hrec, 0, "[prop] [pro\\pblah] [prop]"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 8, "Expected 8, got %d\n", sz); + ok(!lstrcmpA(buffer, "val val"), "Expected \"val val\", got \"%s\"\n", buffer); + + MsiSetPropertyA(package, "b", "ball"); + MsiRecordSetString(hrec, 0, "[\\b]"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 1, "Expected 1, got %d\n", sz); + ok(!lstrcmpA(buffer, "b"), "Expected \"b\", got \"%s\"\n", buffer); + + MsiRecordSetString(hrec, 0, "[\\c]"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 1, "Expected 1, got %d\n", sz); + ok(!lstrcmpA(buffer, "c"), "Expected \"c\", got \"%s\"\n", buffer); + + MsiRecordSetString(hrec, 0, "[\\[]prop]"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 6, "Expected 6, got %d\n", sz); + ok(!lstrcmpA(buffer, "[prop]"), "Expected \"[prop]\", got \"%s\"\n", buffer); + + MsiRecordSetString(hrec, 0, "[\\a]prop]"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 6, "Expected 6, got %d\n", sz); + ok(!lstrcmpA(buffer, "aprop]"), "Expected \"aprop]\", got \"%s\"\n", buffer); + MsiRecordSetString(hrec, 0, "[\\[]Bracket Text[\\]]"); sz = sizeof buffer; r = MsiFormatRecord(package, hrec, buffer, &sz); @@ -1809,8 +1889,19 @@ static void test_formatrecord_package(void) sz = sizeof buffer; r = MsiFormatRecord(package, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - ok( sz == 9, "size wrong\n"); - ok( 0 == strcmp(buffer,"boo "), "wrong output\n"); + ok( sz == 9, "size wrong: %d\n", sz); + ok( 0 == strcmp(buffer,"boo "), "wrong output: %s\n", buffer); + ok(!lstrcmpA(&buffer[5], " hoo"), + "Expected \" hoo\", got \"%s\"\n", &buffer[5]); + + MsiRecordSetString(hrec, 0, "[1] [~abc] [2]"); + MsiRecordSetString(hrec, 1, "boo"); + MsiRecordSetString(hrec, 2, "hoo"); + sz = sizeof(buffer); + r = MsiFormatRecord(package, hrec, buffer, &sz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(sz == 8, "Expected 8, got %d\n", sz); + ok(!lstrcmpA(buffer, "boo hoo"), "Expected \"boo hoo\", got \"%s\"\n", buffer); /* properties */ r = MsiSetProperty(package,"dummy","Bork"); @@ -1835,7 +1926,6 @@ static void test_formatrecord_package(void) ok( sz == 8, "size wrong\n"); ok( 0 == strcmp(buffer,"boo hoo"), "wrong output\n"); - /* nesting tests */ r = MsiSetProperty(package,"dummya","foo"); r = MsiSetProperty(package,"dummyb","baa"); @@ -1852,7 +1942,6 @@ static void test_formatrecord_package(void) ok( sz == 12, "size wrong(%i)\n",sz); ok( 0 == strcmp(buffer,"foo baa whoa"), "wrong output (%s)\n",buffer); - r = MsiSetProperty(package,"dummya","1"); r = MsiSetProperty(package,"dummyb","[2]"); ok( r == ERROR_SUCCESS, "set property failed\n"); @@ -1864,8 +1953,11 @@ static void test_formatrecord_package(void) sz = sizeof buffer; r = MsiFormatRecord(package, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - ok( sz == 9, "size wrong(%i)\n",sz); - ok( 0 == strcmp(buffer,"1 [1] [2]"), "wrong output (%s)\n",buffer); + todo_wine + { + ok( sz == 9, "size wrong(%i)\n",sz); + ok( 0 == strcmp(buffer,"1 [1] [2]"), "wrong output (%s)\n",buffer); + } r = MsiSetProperty(package,"dummya","1"); r = MsiSetProperty(package,"dummyb","a"); @@ -1891,8 +1983,11 @@ static void test_formatrecord_package(void) sz = sizeof buffer; r = MsiFormatRecord(package, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - ok( sz == 11, "size wrong(%i)\n",sz); - ok( 0 == strcmp(buffer,"boo hoo [3]"), "wrong output (%s)\n",buffer); + todo_wine + { + ok( sz == 11, "size wrong(%i)\n",sz); + ok( 0 == strcmp(buffer,"boo hoo [3]"), "wrong output (%s)\n",buffer); + } r = MsiRecordSetString(hrec, 0, "[1] [2] [[3]]"); r = MsiRecordSetString(hrec, 1, "boo"); @@ -1979,7 +2074,7 @@ static void test_formatrecord_package(void) sz = sizeof buffer; MsiRecordSetString(hrec, 0, "{a[one]bc[two]de[one]f}"); r = MsiFormatRecord(package, hrec, buffer, &sz); - ok( r == ERROR_SUCCESS, "format failed\n"); + ok( r == ERROR_SUCCESS, "format failed: %d\n", r); ok( sz == 25, "size wrong(%i)\n",sz); ok( 0 == strcmp(buffer,"amercurybcvenusdemercuryf"), "wrong output (%s)\n",buffer); @@ -2006,38 +2101,39 @@ static void test_formatrecord_package(void) MsiRecordSetString(hrec, 0, "{abc{d[one]ef}"); /* missing final brace */ r = MsiFormatRecord(package, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - ok( sz == 14, "size wrong(%i)\n",sz); - ok( 0 == strcmp(buffer,"abc{dmercuryef"), "wrong output (%s)\n",buffer); + todo_wine + { + ok( sz == 14, "size wrong(%i)\n",sz); + ok( 0 == strcmp(buffer,"abc{dmercuryef"), "wrong output (%s)\n",buffer); + } MsiSetProperty(package, "one", "mercury"); sz = sizeof buffer; MsiRecordSetString(hrec, 0, "{abc{d[one]ef}}"); r = MsiFormatRecord(package, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - ok( sz == 15, "size wrong(%i)\n",sz); - ok( 0 == strcmp(buffer,"abc{dmercuryef}"), "wrong output (%s)\n",buffer); + todo_wine + { + ok( sz == 15, "size wrong(%i)\n",sz); + ok( 0 == strcmp(buffer,"abc{dmercuryef}"), "wrong output (%s)\n",buffer); + } MsiSetProperty(package, "one", "mercury"); sz = sizeof buffer; MsiRecordSetString(hrec, 0, "{abc}{{def}hi{j[one]k}}"); r = MsiFormatRecord(package, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine - { - ok( sz == 5, "size wrong(%i)\n",sz); - ok( 0 == strcmp(buffer,"{abc}"), "wrong output (%s)\n",buffer); - } + ok( sz == 5, "size wrong(%i)\n",sz); + ok( 0 == strcmp(buffer,"{abc}"), "wrong output (%s)\n",buffer); MsiSetProperty(package, "one", "mercury"); + sz = sizeof buffer; MsiRecordSetString(hrec, 0, "{{def}hi{j[one]k}}"); r = MsiFormatRecord(package, hrec, buffer, &sz); ok( r == ERROR_SUCCESS, "format failed\n"); - todo_wine - { - ok( sz == 0, "size wrong(%i)\n",sz); - ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer); - } + ok( sz == 0, "size wrong(%i)\n",sz); + ok( 0 == strcmp(buffer,""), "wrong output (%s)\n",buffer); sz = sizeof(buffer); MsiRecordSetString(hrec, 0, "[1] {[noprop] [twoprop]} {abcdef}"); @@ -2045,11 +2141,8 @@ static void test_formatrecord_package(void) r = MsiFormatRecord(package, hrec, buffer, &sz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(sz == 13, "Expected 13, got %d\n",sz); - todo_wine - { - ok(!lstrcmpA(buffer, "one {abcdef}"), - "Expected \"one {abcdef}\", got \"%s\"\n", buffer); - } + ok(!lstrcmpA(buffer, "one {abcdef}"), + "Expected \"one {abcdef}\", got \"%s\"\n", buffer); sz = sizeof(buffer); MsiRecordSetString(hrec, 0, "[1] {[noprop] [one]} {abcdef}"); @@ -2057,11 +2150,8 @@ static void test_formatrecord_package(void) r = MsiFormatRecord(package, hrec, buffer, &sz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(sz == 13, "Expected 13, got %d\n",sz); - todo_wine - { - ok(!lstrcmpA(buffer, "one {abcdef}"), - "Expected \"one {abcdef}\", got \"%s\"\n", buffer); - } + ok(!lstrcmpA(buffer, "one {abcdef}"), + "Expected \"one {abcdef}\", got \"%s\"\n", buffer); sz = sizeof(buffer); MsiRecordSetString(hrec, 0, "[1] {[one]} {abcdef}"); @@ -2069,11 +2159,8 @@ static void test_formatrecord_package(void) r = MsiFormatRecord(package, hrec, buffer, &sz); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); ok(sz == 20, "Expected 20, got %d\n",sz); - todo_wine - { - ok(!lstrcmpA(buffer, "one mercury {abcdef}"), - "Expected \"one mercury {abcdef}\", got \"%s\"\n", buffer); - } + ok(!lstrcmpA(buffer, "one mercury {abcdef}"), + "Expected \"one mercury {abcdef}\", got \"%s\"\n", buffer); MsiCloseHandle(hrec); diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index d3949081393..b5892c0880e 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -576,6 +576,16 @@ static const CHAR df_duplicate_file_dat[] = "FileKey\tComponent_\tFile_\tDestNam "maximus\tmaximus\tmaximus\taugustus\t\n" "caesar\tmaximus\tmaximus\t\tNONEXISTENT\n"; +static const CHAR wrv_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" + "s72\tS38\ts72\ti2\tS255\tS72\n" + "Component\tComponent\n" + "augustus\t\tMSITESTDIR\t0\t\taugustus\n"; + +static const CHAR wrv_registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n" + "s72\ti2\tl255\tL255\tL0\ts72\n" + "Registry\tRegistry\n" + "regdata\t2\tSOFTWARE\\Wine\\msitest\tValue\t[~]one[~]two[~]three\taugustus"; + typedef struct _msi_table { const CHAR *filename; @@ -864,6 +874,19 @@ static const msi_table df_tables[] = ADD_TABLE(df_duplicate_file), }; +static const msi_table wrv_tables[] = +{ + ADD_TABLE(wrv_component), + ADD_TABLE(directory), + ADD_TABLE(rof_feature), + ADD_TABLE(ci2_feature_comp), + ADD_TABLE(ci2_file), + ADD_TABLE(install_exec_seq), + ADD_TABLE(rof_media), + ADD_TABLE(property), + ADD_TABLE(wrv_registry), +}; + /* cabinet definitions */ /* make the max size large so there is only one cab file */ @@ -3625,6 +3648,43 @@ static void test_duplicatefiles(void) DeleteFile(msifile); } +static void test_writeregistryvalues(void) +{ + UINT r; + LONG res; + HKEY hkey; + DWORD type, size; + CHAR path[MAX_PATH]; + + CreateDirectoryA("msitest", NULL); + create_file("msitest\\augustus", 500); + + create_database(msifile, wrv_tables, sizeof(wrv_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(delete_pf("msitest\\augustus", TRUE), "File installed\n"); + ok(delete_pf("msitest", FALSE), "File installed\n"); + + res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + size = MAX_PATH; + type = REG_MULTI_SZ; + memset(path, 'a', MAX_PATH); + res = RegQueryValueExA(hkey, "Value", NULL, &type, (LPBYTE)path, &size); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + ok(!memcmp(path, "one\0two\0three\0\0", size), "Wrong multi-sz data\n"); + ok(size == 15, "Expected 15, got %d\n", size); + ok(type == REG_MULTI_SZ, "Expected REG_MULTI_SZ, got %d\n", type); + + DeleteFile(msifile); + DeleteFile("msitest\\augustus"); + RemoveDirectory("msitest"); +} + START_TEST(install) { DWORD len; @@ -3667,6 +3727,7 @@ START_TEST(install) test_movefiles(); test_missingcab(); test_duplicatefiles(); + test_writeregistryvalues(); SetCurrentDirectoryA(prev_path); } diff --git a/dlls/msi/tests/msi.c b/dlls/msi/tests/msi.c index a2149c8ef7a..520f0e77582 100644 --- a/dlls/msi/tests/msi.c +++ b/dlls/msi/tests/msi.c @@ -1790,6 +1790,258 @@ static void test_MsiEnumClients(void) RegCloseKey(compkey); } +static void get_version_info(LPSTR path, LPSTR *vercheck, LPDWORD verchecksz, + LPSTR *langcheck, LPDWORD langchecksz) +{ + LPSTR version; + VS_FIXEDFILEINFO *ffi; + DWORD size = GetFileVersionInfoSizeA(path, NULL); + USHORT *lang; + + version = HeapAlloc(GetProcessHeap(), 0, size); + GetFileVersionInfoA(path, 0, size, version); + + VerQueryValueA(version, "\\", (LPVOID *)&ffi, &size); + *vercheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH); + sprintf(*vercheck, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS), + LOWORD(ffi->dwFileVersionMS), HIWORD(ffi->dwFileVersionLS), + LOWORD(ffi->dwFileVersionLS)); + *verchecksz = lstrlenA(*vercheck); + + VerQueryValue(version, "\\VarFileInfo\\Translation", (void **)&lang, &size); + *langcheck = HeapAlloc(GetProcessHeap(), 0, MAX_PATH); + sprintf(*langcheck, "%d", *lang); + *langchecksz = lstrlenA(*langcheck); + + HeapFree(GetProcessHeap(), 0, version); +} + +static void test_MsiGetFileVersion(void) +{ + UINT r; + DWORD versz, langsz; + char version[MAX_PATH]; + char lang[MAX_PATH]; + char path[MAX_PATH]; + LPSTR vercheck, langcheck; + DWORD verchecksz, langchecksz; + + /* NULL szFilePath */ + versz = MAX_PATH; + langsz = MAX_PATH; + lstrcpyA(version, "version"); + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA(NULL, version, &versz, lang, &langsz); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + ok(!lstrcmpA(version, "version"), + "Expected version to be unchanged, got %s\n", version); + ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz); + ok(!lstrcmpA(lang, "lang"), + "Expected lang to be unchanged, got %s\n", lang); + ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz); + + /* empty szFilePath */ + versz = MAX_PATH; + langsz = MAX_PATH; + lstrcpyA(version, "version"); + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA("", version, &versz, lang, &langsz); + ok(r == ERROR_FILE_NOT_FOUND, + "Expected ERROR_FILE_NOT_FOUND, got %d\n", r); + ok(!lstrcmpA(version, "version"), + "Expected version to be unchanged, got %s\n", version); + ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz); + ok(!lstrcmpA(lang, "lang"), + "Expected lang to be unchanged, got %s\n", lang); + ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz); + + /* nonexistent szFilePath */ + versz = MAX_PATH; + langsz = MAX_PATH; + lstrcpyA(version, "version"); + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz); + ok(r == ERROR_FILE_NOT_FOUND, + "Expected ERROR_FILE_NOT_FOUND, got %d\n", r); + ok(!lstrcmpA(version, "version"), + "Expected version to be unchanged, got %s\n", version); + ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz); + ok(!lstrcmpA(lang, "lang"), + "Expected lang to be unchanged, got %s\n", lang); + ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz); + + /* nonexistent szFilePath, valid lpVersionBuf, NULL pcchVersionBuf */ + versz = MAX_PATH; + langsz = MAX_PATH; + lstrcpyA(version, "version"); + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA("nonexistent", version, NULL, lang, &langsz); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + ok(!lstrcmpA(version, "version"), + "Expected version to be unchanged, got %s\n", version); + ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz); + ok(!lstrcmpA(lang, "lang"), + "Expected lang to be unchanged, got %s\n", lang); + ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz); + + /* nonexistent szFilePath, valid lpLangBuf, NULL pcchLangBuf */ + versz = MAX_PATH; + langsz = MAX_PATH; + lstrcpyA(version, "version"); + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA("nonexistent", version, &versz, lang, NULL); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + ok(!lstrcmpA(version, "version"), + "Expected version to be unchanged, got %s\n", version); + ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz); + ok(!lstrcmpA(lang, "lang"), + "Expected lang to be unchanged, got %s\n", lang); + ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz); + + /* nonexistent szFilePath, valid lpVersionBuf, pcchVersionBuf is zero */ + versz = 0; + langsz = MAX_PATH; + lstrcpyA(version, "version"); + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz); + ok(r == ERROR_FILE_NOT_FOUND, + "Expected ERROR_FILE_NOT_FOUND, got %d\n", r); + ok(!lstrcmpA(version, "version"), + "Expected version to be unchanged, got %s\n", version); + ok(versz == 0, "Expected 0, got %d\n", versz); + ok(!lstrcmpA(lang, "lang"), + "Expected lang to be unchanged, got %s\n", lang); + ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz); + + /* nonexistent szFilePath, valid lpLangBuf, pcchLangBuf is zero */ + versz = MAX_PATH; + langsz = 0; + lstrcpyA(version, "version"); + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA("nonexistent", version, &versz, lang, &langsz); + ok(r == ERROR_FILE_NOT_FOUND, + "Expected ERROR_FILE_NOT_FOUND, got %d\n", r); + ok(!lstrcmpA(version, "version"), + "Expected version to be unchanged, got %s\n", version); + ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz); + ok(!lstrcmpA(lang, "lang"), + "Expected lang to be unchanged, got %s\n", lang); + ok(langsz == 0, "Expected 0, got %d\n", langsz); + + /* nonexistent szFilePath, rest NULL */ + r = MsiGetFileVersionA("nonexistent", NULL, NULL, NULL, NULL); + ok(r == ERROR_FILE_NOT_FOUND, + "Expected ERROR_FILE_NOT_FOUND, got %d\n", r); + + create_file("ver.txt", "ver.txt", 20); + + /* file exists, no version information */ + versz = MAX_PATH; + langsz = MAX_PATH; + lstrcpyA(version, "version"); + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA("ver.txt", version, &versz, lang, &langsz); + ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz); + ok(!lstrcmpA(version, "version"), + "Expected version to be unchanged, got %s\n", version); + ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz); + ok(!lstrcmpA(lang, "lang"), + "Expected lang to be unchanged, got %s\n", lang); + ok(r == ERROR_FILE_INVALID, + "Expected ERROR_FILE_INVALID, got %d\n", r); + + DeleteFileA("ver.txt"); + + /* relative path, has version information */ + versz = MAX_PATH; + langsz = MAX_PATH; + lstrcpyA(version, "version"); + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA("kernel32.dll", version, &versz, lang, &langsz); + todo_wine + { + ok(r == ERROR_FILE_NOT_FOUND, + "Expected ERROR_FILE_NOT_FOUND, got %d\n", r); + ok(!lstrcmpA(version, "version"), + "Expected version to be unchanged, got %s\n", version); + ok(versz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, versz); + ok(!lstrcmpA(lang, "lang"), + "Expected lang to be unchanged, got %s\n", lang); + ok(langsz == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, langsz); + } + + GetSystemDirectoryA(path, MAX_PATH); + lstrcatA(path, "\\kernel32.dll"); + + get_version_info(path, &vercheck, &verchecksz, &langcheck, &langchecksz); + + /* absolute path, has version information */ + versz = MAX_PATH; + langsz = MAX_PATH; + lstrcpyA(version, "version"); + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA(path, version, &versz, lang, &langsz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz); + ok(!lstrcmpA(lang, langcheck), "Expected %s, got %s\n", langcheck, lang); + ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz); + ok(!lstrcmpA(version, vercheck), + "Expected %s, got %s\n", vercheck, version); + + /* only check version */ + versz = MAX_PATH; + lstrcpyA(version, "version"); + r = MsiGetFileVersionA(path, version, &versz, NULL, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz); + ok(!lstrcmpA(version, vercheck), + "Expected %s, got %s\n", vercheck, version); + + /* only check language */ + langsz = MAX_PATH; + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(!lstrcmpA(lang, langcheck), "Expected %s, got %s\n", langcheck, lang); + ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz); + + /* get pcchVersionBuf */ + versz = MAX_PATH; + r = MsiGetFileVersionA(path, NULL, &versz, NULL, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz); + + /* get pcchLangBuf */ + langsz = MAX_PATH; + r = MsiGetFileVersionA(path, NULL, NULL, NULL, &langsz); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz); + + /* pcchVersionBuf not big enough */ + versz = 5; + lstrcpyA(version, "version"); + r = MsiGetFileVersionA(path, version, &versz, NULL, NULL); + ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r); + ok(!strncmp(version, vercheck, 4), + "Expected first 4 characters of %s, got %s\n", vercheck, version); + ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz); + + /* pcchLangBuf not big enough */ + langsz = 3; + lstrcpyA(lang, "lang"); + r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz); + ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r); + ok(!strncmp(lang, langcheck, 2), + "Expected first character of %s, got %s\n", langcheck, lang); + ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz); + + HeapFree(GetProcessHeap(), 0, vercheck); + HeapFree(GetProcessHeap(), 0, langcheck); +} + START_TEST(msi) { init_functionpointers(); @@ -1811,4 +2063,6 @@ START_TEST(msi) test_MsiGetProductCode(); test_MsiEnumClients(); } + + test_MsiGetFileVersion(); } diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index ce36fd5a9cd..d6cffcbaaa3 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -75,8 +75,10 @@ @ extern _HUGE MSVCRT__HUGE @ cdecl _Strftime(str long str ptr ptr) @ cdecl _XcptFilter(long ptr) +@ cdecl __CxxDetectRethrow(ptr) @ cdecl -i386 -norelay __CxxFrameHandler(ptr ptr ptr ptr) @ stdcall -i386 __CxxLongjmpUnwind(ptr) +@ cdecl __CxxQueryExceptionSize() @ cdecl __RTCastToVoid(ptr) MSVCRT___RTCastToVoid @ cdecl __RTDynamicCast(ptr long ptr ptr long) MSVCRT___RTDynamicCast @ cdecl __RTtypeid(ptr) MSVCRT___RTtypeid diff --git a/dlls/msvfw32/drawdib.c b/dlls/msvfw32/drawdib.c index 3b308237f2f..137716de3ed 100644 --- a/dlls/msvfw32/drawdib.c +++ b/dlls/msvfw32/drawdib.c @@ -133,6 +133,8 @@ BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd) TRACE("(%p)\n", hdd); + if (!whdd) return FALSE; + whdd->hpal = 0; /* Do not free this */ whdd->hdc = 0; HeapFree(GetProcessHeap(), 0, whdd->lpbi); diff --git a/dlls/msxml3/element.c b/dlls/msxml3/element.c index ba012473d76..6ee88817c00 100644 --- a/dlls/msxml3/element.c +++ b/dlls/msxml3/element.c @@ -458,7 +458,7 @@ static HRESULT WINAPI domelem_getAttribute( { domelem *This = impl_from_IXMLDOMElement( iface ); xmlNodePtr element; - xmlChar *xml_name, *xml_value; + xmlChar *xml_name, *xml_value = NULL; HRESULT hr = S_FALSE; TRACE("(%p)->(%s,%p)\n", This, debugstr_w(name), value); @@ -474,7 +474,12 @@ static HRESULT WINAPI domelem_getAttribute( V_VT(value) = VT_NULL; xml_name = xmlChar_from_wchar( name ); - xml_value = xmlGetNsProp(element, xml_name, NULL); + + if(!xmlValidateNameValue(xml_name)) + hr = E_FAIL; + else + xml_value = xmlGetNsProp(element, xml_name, NULL); + HeapFree(GetProcessHeap(), 0, xml_name); if(xml_value) { diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index 4507d08710b..cbc7c6bdf59 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -156,7 +156,7 @@ static WCHAR szCDataXML[] = {'<','!','[','C','D','A','T','A','[','[','1',']','*' static WCHAR szCDataNodeText[] = {'#','c','d','a','t','a','-','s','e','c','t','i','o','n',0 }; static WCHAR szDocFragmentText[] = {'#','d','o','c','u','m','e','n','t','-','f','r','a','g','m','e','n','t',0 }; -static WCHAR szEntityRef[] = {'E','n','t','i','t','y','r','e','f',0 }; +static WCHAR szEntityRef[] = {'e','n','t','i','t','y','r','e','f',0 }; static WCHAR szEntityRefXML[] = {'&','e','n','t','i','t','y','r','e','f',';',0 }; #define expect_bstr_eq_and_free(bstr, expect) { \ @@ -719,7 +719,7 @@ static void test_domnode( void ) V_VT(&var) = VT_I4; V_I4(&var) = 0x1234; r = IXMLDOMElement_getAttribute( element, str, &var ); - ok( r == S_FALSE, "getAttribute ret %08x\n", r ); + ok( r == E_FAIL, "getAttribute ret %08x\n", r ); ok( V_VT(&var) == VT_NULL, "vt = %x\n", V_VT(&var)); VariantClear(&var); SysFreeString( str ); @@ -1721,6 +1721,7 @@ static void test_XPath(void) ole_expect(IXMLDOMDocument_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL); + VariantClear(&var); todo_wine ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var)); todo_wine expect_eq(V_VT(&var), VT_BSTR, int, "%x"); if (V_VT(&var) == VT_BSTR) @@ -2298,7 +2299,7 @@ static void test_xmlTypes(void) /* test get_xml*/ hr = IXMLDOMEntityReference_get_xml(pEntityRef, &str); ok(hr == S_OK, "ret %08x\n", hr ); - todo_wine ok( !lstrcmpW( str, szEntityRefXML ), "incorrect xml string\n"); + ok( !lstrcmpW( str, szEntityRefXML ), "incorrect xml string\n"); SysFreeString(str); IXMLDOMEntityReference_Release(pEntityRef); diff --git a/dlls/msxml3/tests/xmldoc.c b/dlls/msxml3/tests/xmldoc.c index 1186c9b46dd..0d1c90a491d 100644 --- a/dlls/msxml3/tests/xmldoc.c +++ b/dlls/msxml3/tests/xmldoc.c @@ -270,8 +270,8 @@ static void test_createElement(void) V_I4(&vType) = -1; V_VT(&vName) = VT_NULL; hr = IXMLDocument_createElement(doc, vType, vName, &element); - ok(hr == S_OK, "Expected S_OK, got %d\n", hr); - ok(element != NULL, "Expected non-NULL element\n"); + ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %d\n", hr); + ok(element == NULL, "Expected NULL element\n"); if (element != NULL) { diff --git a/dlls/msxml3/xmldoc.c b/dlls/msxml3/xmldoc.c index a4c0850b095..ee72d1b1575 100644 --- a/dlls/msxml3/xmldoc.c +++ b/dlls/msxml3/xmldoc.c @@ -453,6 +453,9 @@ static HRESULT WINAPI xmldoc_createElement(IXMLDocument *iface, VARIANT vType, if (V_VT(&vType) != VT_I4) return E_INVALIDARG; + if(type_msxml_to_libxml(V_I4(&vType)) == -1) + return E_NOTIMPL; + node = xmlNewNode(NULL, empty); node->type = type_msxml_to_libxml(V_I4(&vType)); diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 5a9961627ae..843f3f012ca 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -1578,9 +1578,6 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io, TRACE("(%p,%p,%p,0x%08x,0x%08x)\n", handle, io, ptr, len, class); - if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) - return io->u.Status; - io->u.Status = STATUS_SUCCESS; switch (class) { @@ -1590,6 +1587,9 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io, struct stat st; const FILE_BASIC_INFORMATION *info = ptr; + if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + return io->u.Status; + if (info->LastAccessTime.QuadPart || info->LastWriteTime.QuadPart) { ULONGLONG sec, nsec; @@ -1641,6 +1641,8 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io, if (fchmod( fd, st.st_mode ) == -1) io->u.Status = FILE_GetNtStatus(); } } + + if (needs_close) close( fd ); } else io->u.Status = STATUS_INVALID_PARAMETER_3; break; @@ -1650,8 +1652,13 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io, { const FILE_POSITION_INFORMATION *info = ptr; + if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + return io->u.Status; + if (lseek( fd, info->CurrentByteOffset.QuadPart, SEEK_SET ) == (off_t)-1) io->u.Status = FILE_GetNtStatus(); + + if (needs_close) close( fd ); } else io->u.Status = STATUS_INVALID_PARAMETER_3; break; @@ -1662,6 +1669,9 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io, struct stat st; const FILE_END_OF_FILE_INFORMATION *info = ptr; + if ((io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + return io->u.Status; + /* first try normal truncate */ if (ftruncate( fd, (off_t)info->EndOfFile.QuadPart ) != -1) break; @@ -1676,6 +1686,8 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io, ftruncate( fd, (off_t)info->EndOfFile.QuadPart ) != -1) break; } io->u.Status = FILE_GetNtStatus(); + + if (needs_close) close( fd ); } else io->u.Status = STATUS_INVALID_PARAMETER_3; break; @@ -1717,7 +1729,6 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io, io->u.Status = STATUS_NOT_IMPLEMENTED; break; } - if (needs_close) close( fd ); io->Information = 0; return io->u.Status; } diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 9bd5678bb37..ae3c84b1b25 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -619,7 +619,7 @@ static void test_debugger(void) if(de.u.CreateProcessInfo.lpBaseOfImage != pNtCurrentTeb()->Peb->ImageBaseAddress) { skip("child process loaded at different address, terminating it\n"); - pNtTerminateProcess(pi.hProcess, 1); + pNtTerminateProcess(pi.hProcess, 0); } } else if (de.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) @@ -710,6 +710,7 @@ static void test_debugger(void) } while (de.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT); + winetest_wait_child_process( pi.hProcess ); ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError()); ok(CloseHandle(pi.hProcess) != 0, "error %u\n", GetLastError()); diff --git a/dlls/ntdsapi/ntdsapi.c b/dlls/ntdsapi/ntdsapi.c index bad284cf249..01acda05e56 100644 --- a/dlls/ntdsapi/ntdsapi.c +++ b/dlls/ntdsapi/ntdsapi.c @@ -135,6 +135,11 @@ DWORD WINAPI DsMakeSpnW(LPCWSTR svc_class, LPCWSTR svc_name, return ERROR_SUCCESS; } +/*********************************************************************** + * DsMakeSpnA (NTDSAPI.@) + * + * See DsMakeSpnW. + */ DWORD WINAPI DsMakeSpnA(LPCSTR svc_class, LPCSTR svc_name, LPCSTR inst_name, USHORT inst_port, LPCSTR ref, DWORD *spn_length, LPSTR spn) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index dcc2769b77a..149cb517b5d 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -562,6 +562,23 @@ void WINAPI MmFreeNonCachedMemory( void *addr, SIZE_T size ) } /*********************************************************************** + * MmPageEntireDriver (NTOSKRNL.EXE.@) + */ +PVOID WINAPI MmPageEntireDriver(PVOID AddrInSection) +{ + TRACE("%p\n", AddrInSection); + return AddrInSection; +} + +/*********************************************************************** + * MmResetDriverPaging (NTOSKRNL.EXE.@) + */ +void WINAPI MmResetDriverPaging(PVOID AddrInSection) +{ + TRACE("%p\n", AddrInSection); +} + +/*********************************************************************** * PsCreateSystemThread (NTOSKRNL.EXE.@) */ NTSTATUS WINAPI PsCreateSystemThread(PHANDLE ThreadHandle, ULONG DesiredAccess, diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 7d509af6d11..dbe21529e43 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -700,7 +700,7 @@ @ stub MmMapViewOfSection @ stub MmMarkPhysicalMemoryAsBad @ stub MmMarkPhysicalMemoryAsGood -@ stub MmPageEntireDriver +@ stdcall MmPageEntireDriver(ptr) @ stub MmPrefetchPages @ stub MmProbeAndLockPages @ stub MmProbeAndLockProcessPages @@ -708,7 +708,7 @@ @ stub MmProtectMdlSystemAddress @ stub MmQuerySystemSize @ stub MmRemovePhysicalMemory -@ stub MmResetDriverPaging +@ stdcall MmResetDriverPaging(ptr) @ stub MmSectionObjectType @ stub MmSecureVirtualMemory @ stub MmSetAddressRangeModified diff --git a/dlls/ole32/Makefile.in b/dlls/ole32/Makefile.in index d6e9eef98b6..cc3867abf86 100644 --- a/dlls/ole32/Makefile.in +++ b/dlls/ole32/Makefile.in @@ -35,6 +35,7 @@ C_SRCS = \ ole32_main.c \ oleobj.c \ oleproxy.c \ + pointermoniker.c \ regsvr.c \ rpc.c \ stg_bigblockfile.c \ diff --git a/dlls/ole32/moniker.h b/dlls/ole32/moniker.h index d3ce652105d..32335c133a5 100644 --- a/dlls/ole32/moniker.h +++ b/dlls/ole32/moniker.h @@ -28,12 +28,14 @@ DEFINE_OLEGUID( CLSID_ItemMoniker, 0x304, 0, 0 ); DEFINE_OLEGUID( CLSID_AntiMoniker, 0x305, 0, 0 ); DEFINE_OLEGUID( CLSID_CompositeMoniker, 0x309, 0, 0 ); DEFINE_OLEGUID( CLSID_ClassMoniker, 0x31a, 0, 0 ); +DEFINE_OLEGUID( CLSID_PointerMoniker, 0x306, 0, 0 ); HRESULT FileMonikerCF_Create(REFIID riid, LPVOID *ppv); HRESULT ItemMonikerCF_Create(REFIID riid, LPVOID *ppv); HRESULT AntiMonikerCF_Create(REFIID riid, LPVOID *ppv); HRESULT CompositeMonikerCF_Create(REFIID riid, LPVOID *ppv); HRESULT ClassMonikerCF_Create(REFIID riid, LPVOID *ppv); +HRESULT PointerMonikerCF_Create(REFIID riid, LPVOID *ppv); /* This function decomposes a String path to a String Table containing all the elements ("\" or "subDirectory" or "Directory" or "FileName") of the path */ int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable); diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 25a195587bc..e1b2250280f 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -92,7 +92,7 @@ @ stdcall CreateItemMoniker(wstr wstr ptr) @ stub CreateObjrefMoniker @ stdcall CreateOleAdviseHolder(ptr) -@ stub CreatePointerMoniker #@ stdcall (ptr ptr) return 0,ERR_NOTIMPLEMENTED +@ stdcall CreatePointerMoniker(ptr ptr) @ stdcall CreateStreamOnHGlobal(ptr long ptr) @ stdcall DllDebugObjectRPCHook(long ptr) @ stdcall -private DllGetClassObject (ptr ptr ptr) diff --git a/dlls/ole32/oleproxy.c b/dlls/ole32/oleproxy.c index 55aa3c5c4d7..4f91d7e57dc 100644 --- a/dlls/ole32/oleproxy.c +++ b/dlls/ole32/oleproxy.c @@ -1030,6 +1030,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) return CompositeMonikerCF_Create(iid, ppv); if (IsEqualCLSID(rclsid, &CLSID_ClassMoniker)) return ClassMonikerCF_Create(iid, ppv); + if (IsEqualCLSID(rclsid, &CLSID_PointerMoniker)) + return PointerMonikerCF_Create(iid, ppv); FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid)); return CLASS_E_CLASSNOTAVAILABLE; diff --git a/dlls/ole32/pointermoniker.c b/dlls/ole32/pointermoniker.c new file mode 100644 index 00000000000..3944f0760dc --- /dev/null +++ b/dlls/ole32/pointermoniker.c @@ -0,0 +1,654 @@ +/* + * Pointer Moniker Implementation + * + * Copyright 1999 Noomen Hamza + * Copyright 2008 Robert Shearman (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 +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winuser.h" +#include "objbase.h" +#include "oleidl.h" +#include "wine/debug.h" +#include "moniker.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +/* PointerMoniker data structure */ +typedef struct PointerMonikerImpl{ + + const IMonikerVtbl* lpvtbl; /* VTable relative to the IMoniker interface.*/ + + LONG ref; /* reference counter for this object */ + + IUnknown *pObject; /* custom marshaler */ +} PointerMonikerImpl; + +static HRESULT WINAPI +PointerMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) +{ + PointerMonikerImpl *This = (PointerMonikerImpl *)iface; + + TRACE("(%p,%p,%p)\n",This,riid,ppvObject); + + /* Perform a sanity check on the parameters.*/ + if ( (This==0) || (ppvObject==0) ) + return E_INVALIDARG; + + /* Initialize the return parameter */ + *ppvObject = 0; + + /* Compare the riid with the interface IDs implemented by this object.*/ + if (IsEqualIID(&IID_IUnknown, riid) || + IsEqualIID(&IID_IPersist, riid) || + IsEqualIID(&IID_IPersistStream, riid) || + IsEqualIID(&IID_IMoniker, riid)) + *ppvObject = iface; + + /* Check that we obtained an interface.*/ + if ((*ppvObject)==0) + return E_NOINTERFACE; + + /* always increase the reference count by one when it is successful */ + IMoniker_AddRef(iface); + + return S_OK; +} + +/****************************************************************************** + * PointerMoniker_AddRef + ******************************************************************************/ +static ULONG WINAPI +PointerMonikerImpl_AddRef(IMoniker* iface) +{ + PointerMonikerImpl *This = (PointerMonikerImpl *)iface; + + TRACE("(%p)\n",This); + + return InterlockedIncrement(&This->ref); +} + +/****************************************************************************** + * PointerMoniker_Release + ******************************************************************************/ +static ULONG WINAPI +PointerMonikerImpl_Release(IMoniker* iface) +{ + PointerMonikerImpl *This = (PointerMonikerImpl *)iface; + ULONG ref; + + TRACE("(%p)\n",This); + + ref = InterlockedDecrement(&This->ref); + + /* destroy the object if there's no more reference on it */ + if (ref == 0) + { + if (This->pObject) IUnknown_Release(This->pObject); + HeapFree(GetProcessHeap(),0,This); + } + + return ref; +} + +/****************************************************************************** + * PointerMoniker_GetClassID + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID) +{ + TRACE("(%p,%p)\n",iface,pClassID); + + if (pClassID==NULL) + return E_POINTER; + + *pClassID = CLSID_PointerMoniker; + + return S_OK; +} + +/****************************************************************************** + * PointerMoniker_IsDirty + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_IsDirty(IMoniker* iface) +{ + /* Note that the OLE-provided implementations of the IPersistStream::IsDirty + method in the OLE-provided moniker interfaces always return S_FALSE because + their internal state never changes. */ + + TRACE("(%p)\n",iface); + + return S_FALSE; +} + +/****************************************************************************** + * PointerMoniker_Load + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_Load(IMoniker* iface,IStream* pStm) +{ + TRACE("(%p)\n", pStm); + + return E_NOTIMPL; +} + +/****************************************************************************** + * PointerMoniker_Save + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty) +{ + TRACE("(%p, %d)\n", pStm, fClearDirty); + + return E_NOTIMPL; +} + +/****************************************************************************** + * PointerMoniker_GetSizeMax + * + * PARAMS + * pcbSize [out] Pointer to size of stream needed to save object + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize) +{ + TRACE("(%p,%p)\n",iface,pcbSize); + + if (!pcbSize) + return E_POINTER; + + pcbSize->u.LowPart = 0; + pcbSize->u.HighPart = 0; + + return E_NOTIMPL; +} + +/****************************************************************************** + * PointerMoniker_BindToObject + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, + REFIID riid, VOID** ppvResult) +{ + PointerMonikerImpl *This = (PointerMonikerImpl *)iface; + + TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult); + + if (!This->pObject) + return E_UNEXPECTED; + + return IUnknown_QueryInterface(This->pObject, riid, ppvResult); +} + +/****************************************************************************** + * PointerMoniker_BindToStorage + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, + REFIID riid, VOID** ppvResult) +{ + PointerMonikerImpl *This = (PointerMonikerImpl *)iface; + + TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult); + + if (!This->pObject) + return E_UNEXPECTED; + + return IUnknown_QueryInterface(This->pObject, riid, ppvResult); +} + +/****************************************************************************** + * PointerMoniker_Reduce + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar, + IMoniker** ppmkToLeft, IMoniker** ppmkReduced) +{ + TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced); + + if (ppmkReduced==NULL) + return E_POINTER; + + PointerMonikerImpl_AddRef(iface); + + *ppmkReduced=iface; + + return MK_S_REDUCED_TO_SELF; +} +/****************************************************************************** + * PointerMoniker_ComposeWith + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight, + BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite) +{ + + HRESULT res=S_OK; + DWORD mkSys,mkSys2; + IEnumMoniker* penumMk=0; + IMoniker *pmostLeftMk=0; + IMoniker* tempMkComposite=0; + + TRACE("(%p,%d,%p)\n", pmkRight, fOnlyIfNotGeneric, ppmkComposite); + + if ((ppmkComposite==NULL)||(pmkRight==NULL)) + return E_POINTER; + + *ppmkComposite=0; + + IMoniker_IsSystemMoniker(pmkRight,&mkSys); + + /* If pmkRight is an anti-moniker, the returned moniker is NULL */ + if(mkSys==MKSYS_ANTIMONIKER) + return res; + + else + /* if pmkRight is a composite whose leftmost component is an anti-moniker, */ + /* the returned moniker is the composite after the leftmost anti-moniker is removed. */ + + if(mkSys==MKSYS_GENERICCOMPOSITE){ + + res=IMoniker_Enum(pmkRight,TRUE,&penumMk); + + if (FAILED(res)) + return res; + + res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL); + + IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2); + + if(mkSys2==MKSYS_ANTIMONIKER){ + + IMoniker_Release(pmostLeftMk); + + tempMkComposite=iface; + IMoniker_AddRef(iface); + + while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){ + + res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite); + + IMoniker_Release(tempMkComposite); + IMoniker_Release(pmostLeftMk); + + tempMkComposite=*ppmkComposite; + IMoniker_AddRef(tempMkComposite); + } + return res; + } + else + return CreateGenericComposite(iface,pmkRight,ppmkComposite); + } + /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic + composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns + a NULL moniker and a return value of MK_E_NEEDGENERIC */ + else + if (!fOnlyIfNotGeneric) + return CreateGenericComposite(iface,pmkRight,ppmkComposite); + + else + return MK_E_NEEDGENERIC; +} + +/****************************************************************************** + * PointerMoniker_Enum + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) +{ + TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker); + + if (ppenumMoniker == NULL) + return E_POINTER; + + *ppenumMoniker = NULL; + + return S_OK; +} + +/****************************************************************************** + * PointerMoniker_IsEqual + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) +{ + PointerMonikerImpl *This = (PointerMonikerImpl *)iface; + DWORD mkSys; + + TRACE("(%p,%p)\n",iface,pmkOtherMoniker); + + if (pmkOtherMoniker==NULL) + return S_FALSE; + + IMoniker_IsSystemMoniker(pmkOtherMoniker,&mkSys); + + if (mkSys==MKSYS_POINTERMONIKER) + { + PointerMonikerImpl *pOtherMoniker = (PointerMonikerImpl *)pmkOtherMoniker; + return This->pObject == pOtherMoniker->pObject ? S_OK : S_FALSE; + } + else + return S_FALSE; +} + +/****************************************************************************** + * PointerMoniker_Hash + ******************************************************************************/ +static HRESULT WINAPI PointerMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) +{ + PointerMonikerImpl *This = (PointerMonikerImpl *)iface; + + if (pdwHash==NULL) + return E_POINTER; + + *pdwHash = (DWORD)This->pObject; + + return S_OK; +} + +/****************************************************************************** + * PointerMoniker_IsRunning + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, + IMoniker* pmkNewlyRunning) +{ + TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning); + + return S_OK; +} + +/****************************************************************************** + * PointerMoniker_GetTimeOfLastChange + ******************************************************************************/ +static HRESULT WINAPI PointerMonikerImpl_GetTimeOfLastChange(IMoniker* iface, + IBindCtx* pbc, + IMoniker* pmkToLeft, + FILETIME* pAntiTime) +{ + TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime); + return E_NOTIMPL; +} + +/****************************************************************************** + * PointerMoniker_Inverse + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) +{ + TRACE("(%p,%p)\n",iface,ppmk); + + return CreateAntiMoniker(ppmk); +} + +/****************************************************************************** + * PointerMoniker_CommonPrefixWith + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) +{ + TRACE("(%p, %p)\n", pmkOther, ppmkPrefix); + + *ppmkPrefix = NULL; + + if (PointerMonikerImpl_IsEqual(iface, pmkOther)) + { + IMoniker_AddRef(iface); + + *ppmkPrefix=iface; + + return MK_S_US; + } + else + return MK_E_NOPREFIX; +} + +/****************************************************************************** + * PointerMoniker_RelativePathTo + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) +{ + TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath); + + if (ppmkRelPath==NULL) + return E_POINTER; + + *ppmkRelPath = NULL; + + return E_NOTIMPL; +} + +/****************************************************************************** + * PointerMoniker_GetDisplayName + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc, + IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName) +{ + TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName); + + if (ppszDisplayName==NULL) + return E_POINTER; + + *ppszDisplayName = NULL; + return E_NOTIMPL; +} + +/****************************************************************************** + * PointerMoniker_ParseDisplayName + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, + IMoniker* pmkToLeft, LPOLESTR pszDisplayName, + ULONG* pchEaten, IMoniker** ppmkOut) +{ + PointerMonikerImpl *This = (PointerMonikerImpl *)iface; + HRESULT hr; + IParseDisplayName *pPDN; + + TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut); + + if (pmkToLeft) + return MK_E_SYNTAX; + + if (!This->pObject) + return E_UNEXPECTED; + + hr = IUnknown_QueryInterface(This->pObject, &IID_IParseDisplayName, (void **)&pPDN); + if (FAILED(hr)) + return hr; + + hr = IParseDisplayName_ParseDisplayName(pPDN, pbc, pszDisplayName, pchEaten, ppmkOut); + IParseDisplayName_Release(pPDN); + + return hr; +} + +/****************************************************************************** + * PointerMoniker_IsSystemMoniker + ******************************************************************************/ +static HRESULT WINAPI +PointerMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) +{ + TRACE("(%p,%p)\n",iface,pwdMksys); + + if (!pwdMksys) + return E_POINTER; + + *pwdMksys = MKSYS_POINTERMONIKER; + + return S_OK; +} + +/********************************************************************************/ +/* Virtual function table for the PointerMonikerImpl class which include IPersist,*/ +/* IPersistStream and IMoniker functions. */ +static const IMonikerVtbl VT_PointerMonikerImpl = +{ + PointerMonikerImpl_QueryInterface, + PointerMonikerImpl_AddRef, + PointerMonikerImpl_Release, + PointerMonikerImpl_GetClassID, + PointerMonikerImpl_IsDirty, + PointerMonikerImpl_Load, + PointerMonikerImpl_Save, + PointerMonikerImpl_GetSizeMax, + PointerMonikerImpl_BindToObject, + PointerMonikerImpl_BindToStorage, + PointerMonikerImpl_Reduce, + PointerMonikerImpl_ComposeWith, + PointerMonikerImpl_Enum, + PointerMonikerImpl_IsEqual, + PointerMonikerImpl_Hash, + PointerMonikerImpl_IsRunning, + PointerMonikerImpl_GetTimeOfLastChange, + PointerMonikerImpl_Inverse, + PointerMonikerImpl_CommonPrefixWith, + PointerMonikerImpl_RelativePathTo, + PointerMonikerImpl_GetDisplayName, + PointerMonikerImpl_ParseDisplayName, + PointerMonikerImpl_IsSystemMoniker +}; + +/****************************************************************************** + * PointerMoniker_Construct (local function) + *******************************************************************************/ +static void PointerMonikerImpl_Construct(PointerMonikerImpl* This, IUnknown *punk) +{ + TRACE("(%p)\n",This); + + /* Initialize the virtual fgunction table. */ + This->lpvtbl = &VT_PointerMonikerImpl; + This->ref = 1; + if (punk) + IUnknown_AddRef(punk); + This->pObject = punk; +} + +/*********************************************************************** + * CreatePointerMoniker (OLE32.@) + * + * Creates a moniker which represents a pointer. + * + * PARAMS + * punk [I] Pointer to the object to represent. + * ppmk [O] Address that receives the pointer to the created moniker. + * + * RETURNS + * Success: S_OK. + * Failure: Any HRESULT code. + */ +HRESULT WINAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER *ppmk) +{ + PointerMonikerImpl *This; + + FIXME("(%p, %p): stub\n", punk, ppmk); + + if (!ppmk) + return E_INVALIDARG; + + This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + if (!This) + { + *ppmk = NULL; + return E_OUTOFMEMORY; + } + + PointerMonikerImpl_Construct(This, punk); + *ppmk = (IMoniker *)&This->lpvtbl; + return S_OK; +} + +static HRESULT WINAPI PointerMonikerCF_QueryInterface(LPCLASSFACTORY iface, + REFIID riid, LPVOID *ppv) +{ + *ppv = NULL; + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) + { + *ppv = iface; + IUnknown_AddRef(iface); + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG WINAPI PointerMonikerCF_AddRef(LPCLASSFACTORY iface) +{ + return 2; /* non-heap based object */ +} + +static ULONG WINAPI PointerMonikerCF_Release(LPCLASSFACTORY iface) +{ + return 1; /* non-heap based object */ +} + +static HRESULT WINAPI PointerMonikerCF_CreateInstance(LPCLASSFACTORY iface, + LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) +{ + IMoniker *pMoniker; + HRESULT hr; + + TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv); + + *ppv = NULL; + + if (pUnk) + return CLASS_E_NOAGGREGATION; + + hr = CreatePointerMoniker(NULL, &pMoniker); + if (FAILED(hr)) + return hr; + + hr = IMoniker_QueryInterface(pMoniker, riid, ppv); + + if (FAILED(hr)) + IMoniker_Release(pMoniker); + + return hr; +} + +static HRESULT WINAPI PointerMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) +{ + FIXME("(%d), stub!\n",fLock); + return S_OK; +} + +static const IClassFactoryVtbl PointerMonikerCFVtbl = +{ + PointerMonikerCF_QueryInterface, + PointerMonikerCF_AddRef, + PointerMonikerCF_Release, + PointerMonikerCF_CreateInstance, + PointerMonikerCF_LockServer +}; +static const IClassFactoryVtbl *PointerMonikerCF = &PointerMonikerCFVtbl; + +HRESULT PointerMonikerCF_Create(REFIID riid, LPVOID *ppv) +{ + return IClassFactory_QueryInterface((IClassFactory *)&PointerMonikerCF, riid, ppv); +} diff --git a/dlls/ole32/regsvr.c b/dlls/ole32/regsvr.c index 51b4f0644b6..e4109317b12 100644 --- a/dlls/ole32/regsvr.c +++ b/dlls/ole32/regsvr.c @@ -403,9 +403,6 @@ error_close_progid_key: static GUID const CLSID_StdOleLink = { 0x00000300, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; -static GUID const CLSID_PointerMoniker = { - 0x00000306, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; - static GUID const CLSID_PackagerMoniker = { 0x00000308, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} }; diff --git a/dlls/ole32/tests/marshal.c b/dlls/ole32/tests/marshal.c index 035a725f96b..c7f79961bcf 100644 --- a/dlls/ole32/tests/marshal.c +++ b/dlls/ole32/tests/marshal.c @@ -2575,7 +2575,7 @@ static void test_local_server(void) quit_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); SetEvent(quit_event); - WaitForSingleObject(process, INFINITE); + winetest_wait_child_process( process ); CloseHandle(quit_event); CloseHandle(process); } diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 9068f27e335..3f3579ae765 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -1589,6 +1589,113 @@ static void test_generic_composite_moniker(void) IMoniker_Release(moniker); } +static void test_pointer_moniker(void) +{ + HRESULT hr; + IMoniker *moniker; + DWORD moniker_type; + DWORD hash; + IBindCtx *bindctx; + FILETIME filetime; + IMoniker *inverse; + IUnknown *unknown; + IStream *stream; + IROTData *rotdata; + LPOLESTR display_name; + + cLocks = 0; + + hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL); + ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr); + + hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker); + ok_ole_success(hr, CreatePointerMoniker); + if (!moniker) return; + + ok_more_than_one_lock(); + + /* Display Name */ + + hr = CreateBindCtx(0, &bindctx); + ok_ole_success(hr, CreateBindCtx); + + hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name); + ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr); + + IBindCtx_Release(bindctx); + + hr = IMoniker_IsDirty(moniker); + ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr); + + /* IROTData::GetComparisonData test */ + + hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata); + ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr); + + /* Saving */ + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok_ole_success(hr, CreateStreamOnHGlobal); + + hr = IMoniker_Save(moniker, stream, TRUE); + ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr); + + IStream_Release(stream); + + /* Hashing */ + hr = IMoniker_Hash(moniker, &hash); + ok_ole_success(hr, IMoniker_Hash); + ok(hash == (DWORD)&Test_ClassFactory, + "Hash value should have been 0x%08x, instead of 0x%08x\n", + (DWORD)&Test_ClassFactory, hash); + + /* IsSystemMoniker test */ + hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); + ok_ole_success(hr, IMoniker_IsSystemMoniker); + ok(moniker_type == MKSYS_POINTERMONIKER, + "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n", + moniker_type); + + hr = IMoniker_Inverse(moniker, &inverse); + ok_ole_success(hr, IMoniker_Inverse); + IMoniker_Release(inverse); + + hr = CreateBindCtx(0, &bindctx); + ok_ole_success(hr, CreateBindCtx); + + /* IsRunning test */ + hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL); + ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr); + + hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime); + ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr); + + hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); + ok_ole_success(hr, IMoniker_BindToObject); + IUnknown_Release(unknown); + + hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); + ok_ole_success(hr, IMoniker_BindToStorage); + IUnknown_Release(unknown); + + IMoniker_Release(moniker); + + ok_no_locks(); + + hr = CreatePointerMoniker(NULL, &moniker); + ok_ole_success(hr, CreatePointerMoniker); + + hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); + ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr); + + hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown); + ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr); + + IBindCtx_Release(bindctx); + + IMoniker_Release(moniker); +} + static void test_bind_context(void) { HRESULT hr; @@ -1700,6 +1807,7 @@ START_TEST(moniker) test_item_moniker(); test_anti_moniker(); test_generic_composite_moniker(); + test_pointer_moniker(); /* FIXME: test moniker creation funcs and parsing other moniker formats */ diff --git a/dlls/oleaut32/olefont.c b/dlls/oleaut32/olefont.c index 3376c0cbc4b..fe787a7db70 100644 --- a/dlls/oleaut32/olefont.c +++ b/dlls/oleaut32/olefont.c @@ -1215,6 +1215,7 @@ static HRESULT WINAPI OLEFontImpl_GetTypeInfo( return hres; } hres = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IFontDisp, ppTInfo); + ITypeLib_Release(tl); if (FAILED(hres)) { FIXME("Did not IDispatch typeinfo from typelib, hres %x\n",hres); } diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c index d0c5f63ed04..27c2ac9e23e 100644 --- a/dlls/oleaut32/olepicture.c +++ b/dlls/oleaut32/olepicture.c @@ -1237,6 +1237,7 @@ static HRESULT OLEPictureImpl_LoadGif(OLEPictureImpl *This, BYTE *xbuf, ULONG xr This->desc.picType = PICTYPE_BITMAP; OLEPictureImpl_SetBitmap(This); DGifCloseFile(gif); + HeapFree(GetProcessHeap(),0,bmi); HeapFree(GetProcessHeap(),0,bytes); return S_OK; } diff --git a/dlls/oleaut32/tests/olefont.c b/dlls/oleaut32/tests/olefont.c index 1e6678b3499..11d6169a242 100644 --- a/dlls/oleaut32/tests/olefont.c +++ b/dlls/oleaut32/tests/olefont.c @@ -171,6 +171,7 @@ static void test_type_info(void) ok(hres == S_OK, "GetNames returned 0x%08x instead of S_OK.\n", hres); ok(n == 1, "GetNames returned %d names instead of 1.\n", n); ok(!lstrcmpiW(names[0],name_Name), "DISPID_FONT_NAME doesn't get 'Names'.\n"); + SysFreeString(names[0]); ITypeInfo_Release(pTInfo); diff --git a/dlls/oleaut32/tests/safearray.c b/dlls/oleaut32/tests/safearray.c index 1857ab5a5ca..2350eb48c24 100644 --- a/dlls/oleaut32/tests/safearray.c +++ b/dlls/oleaut32/tests/safearray.c @@ -355,15 +355,24 @@ static void test_safearray(void) SafeArrayPtrOfIndex(a, indices, (void **)&ptr1); ok(*(WORD *)ptr1 == 0x55aa, "Data not preserved when resizing array\n"); + hres = SafeArrayDestroy(a); + ok(hres == S_OK,"SAD faild with hres %x\n", hres); + bounds[0].cElements = 0; bounds[0].lLbound = 1; bounds[1].cElements = 2; bounds[1].lLbound = 23; a = SafeArrayCreate(VT_I4,2,bounds); ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n"); + + hres = SafeArrayDestroy(a); + ok(hres == S_OK,"SAD faild with hres %x\n", hres); bounds[0].cElements = 1; bounds[0].lLbound = 1; bounds[1].cElements = 0; bounds[1].lLbound = 23; a = SafeArrayCreate(VT_I4,2,bounds); ok(a != NULL,"SAC(VT_INT32,2,...) with 0 element dim failed.\n"); + hres = SafeArrayDestroy(a); + ok(hres == S_OK,"SAD faild with hres %x\n", hres); + bounds[0].cElements = 42; bounds[0].lLbound = 1; bounds[1].cElements = 2; bounds[1].lLbound = 23; a = SafeArrayCreate(VT_I4,2,bounds); @@ -443,6 +452,9 @@ static void test_safearray(void) hres = SafeArrayUnaccessData(a); ok(S_OK == hres, "SAUAD failed with 0x%x\n", hres); + hres = SafeArrayDestroy(a); + ok(hres == S_OK,"SAD faild with hres %x\n", hres); + for (i=0;i VT_BSTR failed with %x\n",hres); ok(V_VT(&v) == VT_BSTR,"CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.v\n",V_VT(&v)); ok(V_BSTR(&v)[0] == 0x6548,"First letter are not 'He', but %x\n", V_BSTR(&v)[0]); + VariantClear(&v); /* check locking functions */ a = SafeArrayCreate(VT_I4, 1, &bound); @@ -560,7 +576,6 @@ static void test_safearray(void) hres = SafeArrayDestroyDescriptor(a); ok(hres == S_OK,"SADD with data in array failed with hres %x\n",hres); - /* IID functions */ /* init a small stack safearray */ if (pSafeArraySetIID) { @@ -574,6 +589,9 @@ static void test_safearray(void) ok((a->fFeatures & FADF_HAVEIID) == 0,"newly allocated descriptor with SAAD should not have FADF_HAVEIID\n"); hres = pSafeArraySetIID(a,&iid); ok(hres == E_INVALIDARG,"SafeArraySetIID of newly allocated descriptor with SAAD should return E_INVALIDARG, but %x\n",hres); + + hres = SafeArrayDestroyDescriptor(a); + ok(hres == S_OK,"SADD failed with hres %x\n",hres); } if (!pSafeArrayAllocDescriptorEx) @@ -692,6 +710,9 @@ static void test_SafeArrayAllocDestroyDescriptor(void) hres = SafeArrayAllocData(sa); ok(hres == S_OK, "SafeArrayAllocData gave hres 0x%x\n", hres); + + hres = SafeArrayDestroy(sa); + ok(hres == S_OK,"SafeArrayDestroy failed with hres %x\n",hres); } static void test_SafeArrayCreateLockDestroy(void) @@ -808,7 +829,7 @@ static void test_SafeArrayCreateLockDestroy(void) ok(hres == S_OK, "Unlock VARTYPE %d (@%d dims) hres 0x%x\n", vt, dimension, hres); - hres = SafeArrayDestroyDescriptor(sa); + hres = SafeArrayDestroy(sa); ok(hres == S_OK, "destroy VARTYPE %d (@%d dims) hres 0x%x\n", vt, dimension, hres); } @@ -829,6 +850,9 @@ static void test_VectorCreateLockDestroy(void) sa = pSafeArrayCreateVector(VT_UI1, 0, 0); ok(sa != NULL, "SACV with 0 elements failed.\n"); + hres = SafeArrayDestroy(sa); + ok(hres == S_OK, "SafeArrayDestroy failed with hres %x\n",hres); + /* Test all VARTYPES in different lengths */ for (element = 1; element <= 101; element += 10) { @@ -861,7 +885,7 @@ static void test_VectorCreateLockDestroy(void) ok(hres == S_OK, "Unlock VARTYPE %d (@%d elements) failed; hres 0x%x\n", vt, element, hres); - hres = SafeArrayDestroyDescriptor(sa); + hres = SafeArrayDestroy(sa); ok(hres == S_OK, "destroy VARTYPE %d (@%d elements) failed; hres 0x%x\n", vt, element, hres); } @@ -1085,6 +1109,8 @@ static void test_SafeArrayGetPutElement_BSTR(void) if (hres == S_OK) ok(SysStringLen(value) == SysStringLen(gotvalue), "Got len %d instead of %d\n", SysStringLen(gotvalue), SysStringLen(value)); SafeArrayDestroy(sa); + SysFreeString(value); + SysFreeString(gotvalue); } static int tunk_xref = 0; @@ -1603,6 +1629,7 @@ static void test_SafeArrayChangeTypeEx(void) hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_BSTR); ok(hres != S_OK, "CTE VT_ARRAY|VT %d->BSTR succeeded\n", vt); VariantClear(&v2); + VariantClear(&v); } /* Can't change an array of one type into array of another type , even @@ -1630,6 +1657,7 @@ static void test_SafeArrayChangeTypeEx(void) V_ARRAY(&v) = sa; hres = VariantChangeTypeEx(&v2, &v, 0, 0, VT_ARRAY|VT_UI1); ok(hres == S_OK, "CTE VT_ARRAY|VT_UI1->VT_ARRAY|VT_UI1 returned %x\n", hres); + SafeArrayDestroy(sa); } /* NULL/EMPTY */ diff --git a/dlls/oleaut32/tests/tmarshal.c b/dlls/oleaut32/tests/tmarshal.c index 7e958defc80..98ed4288980 100644 --- a/dlls/oleaut32/tests/tmarshal.c +++ b/dlls/oleaut32/tests/tmarshal.c @@ -785,6 +785,7 @@ static void test_typelibmarshal(void) hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); ok_ole_success(hr, CreateStreamOnHGlobal); tid = start_host_object(pStream, &IID_IKindaEnumWidget, (IUnknown *)pKEW, MSHLFLAGS_NORMAL, &thread); + IKindaEnumWidget_Release(pKEW); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW); @@ -1163,6 +1164,7 @@ static void test_DispCallFunc(void) VariantClear(&varresult); VariantClear(&vararg[1]); VariantClear(&vararg[2]); + IWidget_Release(pWidget); } START_TEST(tmarshal) diff --git a/dlls/oleaut32/tmarshal.c b/dlls/oleaut32/tmarshal.c index 9649705bf9d..52c8e8a228e 100644 --- a/dlls/oleaut32/tmarshal.c +++ b/dlls/oleaut32/tmarshal.c @@ -1468,6 +1468,7 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) hres = remoteresult; exit: + IRpcChannelBuffer_FreeBuffer(chanbuf,&msg); for (i = 0; i < nrofnames; i++) SysFreeString(names[i]); HeapFree(GetProcessHeap(),0,buf.base); diff --git a/dlls/olecli32/olecli.h b/dlls/olecli32/olecli.h new file mode 100644 index 00000000000..8430a7cc090 --- /dev/null +++ b/dlls/olecli32/olecli.h @@ -0,0 +1,129 @@ +/* + * OLECLI library + * + * Copyright 1995 Martin von Loewis + * + * 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 + */ + +typedef enum +{ + OLE_OK, + OLE_WAIT_FOR_RELEASE, + OLE_BUSY, + OLE_ERROR_PROTECT_ONLY, + OLE_ERROR_MEMORY, + OLE_ERROR_STREAM, + OLE_ERROR_STATIC, + OLE_ERROR_BLANK, + OLE_ERROR_DRAW, + OLE_ERROR_METAFILE, + OLE_ERROR_ABORT, + OLE_ERROR_CLIPBOARD, + OLE_ERROR_FORMAT, + OLE_ERROR_OBJECT, + OLE_ERROR_OPTION, + OLE_ERROR_PROTOCOL, + OLE_ERROR_ADDRESS, + OLE_ERROR_NOT_EQUAL, + OLE_ERROR_HANDLE, + OLE_ERROR_GENERIC, + OLE_ERROR_CLASS, + OLE_ERROR_SYNTAX, + OLE_ERROR_DATATYPE, + OLE_ERROR_PALETTE, + OLE_ERROR_NOT_LINK, + OLE_ERROR_NOT_EMPTY, + OLE_ERROR_SIZE, + OLE_ERROR_DRIVE, + OLE_ERROR_NETWORK, + OLE_ERROR_NAME, + OLE_ERROR_TEMPLATE, + OLE_ERROR_NEW, + OLE_ERROR_EDIT, + OLE_ERROR_OPEN, + OLE_ERROR_NOT_OPEN, + OLE_ERROR_LAUNCH, + OLE_ERROR_COMM, + OLE_ERROR_TERMINATE, + OLE_ERROR_COMMAND, + OLE_ERROR_SHOW, + OLE_ERROR_DOVERB, + OLE_ERROR_ADVISE_NATIVE, + OLE_ERROR_ADVISE_PICT, + OLE_ERROR_ADVISE_RENAME, + OLE_ERROR_POKE_NATIVE, + OLE_ERROR_REQUEST_NATIVE, + OLE_ERROR_REQUEST_PICT, + OLE_ERROR_SERVER_BLOCKED, + OLE_ERROR_REGISTRATION, + OLE_ERROR_ALREADY_REGISTERED, + OLE_ERROR_TASK, + OLE_ERROR_OUTOFDATE, + OLE_ERROR_CANT_UPDATE_CLIENT, + OLE_ERROR_UPDATE, + OLE_ERROR_SETDATA_FORMAT, + OLE_ERROR_STATIC_FROM_OTHER_OS, + OLE_WARN_DELETE_DATA = 1000 +} OLESTATUS; + +typedef enum +{ + olerender_none, + olerender_draw, + olerender_format +} OLEOPT_RENDER; + +typedef enum +{ + oleupdate_always, + oleupdate_onsave, + oleupdate_oncall, + oleupdate_onclose +} OLEOPT_UPDATE; + +typedef enum { + OLE_NONE, /* none */ + OLE_DELETE, /* delete object */ + OLE_LNKPASTE, /* link paste */ + OLE_EMBPASTE, /* paste(and update) */ + OLE_SHOW, + OLE_RUN, + OLE_ACTIVATE, + OLE_UPDATE, + OLE_CLOSE, + OLE_RECONNECT, + OLE_SETUPDATEOPTIONS, + OLE_SERVERRUNLAUNCH, /* unlaunch (terminate?) server */ + OLE_LOADFROMSTREAM, /* (auto reconnect) */ + OLE_SETDATA, /* OleSetData */ + OLE_REQUESTDATA, /* OleRequestData */ + OLE_OTHER, + OLE_CREATE, + OLE_CREATEFROMTEMPLATE, + OLE_CREATELINKFROMFILE, + OLE_COPYFROMLNK, + OLE_CREATREFROMFILE, + OLE_CREATEINVISIBLE +} OLE_RELEASE_METHOD; + +typedef LONG LHCLIENTDOC; +typedef struct _OLEOBJECT *_LPOLEOBJECT; +typedef struct _OLECLIENT *LPOLECLIENT; +typedef LONG OLECLIPFORMAT;/* dunno about this type, please change/add */ +typedef OLEOPT_UPDATE *LPOLEOPT_UPDATE; +typedef LPCSTR LPCOLESTR16; + +struct _OLESTREAM; diff --git a/dlls/olecli32/olecli16.c b/dlls/olecli32/olecli16.c index a1da30a6901..a37254ba309 100644 --- a/dlls/olecli32/olecli16.c +++ b/dlls/olecli32/olecli16.c @@ -31,120 +31,11 @@ #include "wingdi.h" #include "wownt32.h" #include "objbase.h" +#include "olecli.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); -typedef enum -{ - OLE_OK, - OLE_WAIT_FOR_RELEASE, - OLE_BUSY, - OLE_ERROR_PROTECT_ONLY, - OLE_ERROR_MEMORY, - OLE_ERROR_STREAM, - OLE_ERROR_STATIC, - OLE_ERROR_BLANK, - OLE_ERROR_DRAW, - OLE_ERROR_METAFILE, - OLE_ERROR_ABORT, - OLE_ERROR_CLIPBOARD, - OLE_ERROR_FORMAT, - OLE_ERROR_OBJECT, - OLE_ERROR_OPTION, - OLE_ERROR_PROTOCOL, - OLE_ERROR_ADDRESS, - OLE_ERROR_NOT_EQUAL, - OLE_ERROR_HANDLE, - OLE_ERROR_GENERIC, - OLE_ERROR_CLASS, - OLE_ERROR_SYNTAX, - OLE_ERROR_DATATYPE, - OLE_ERROR_PALETTE, - OLE_ERROR_NOT_LINK, - OLE_ERROR_NOT_EMPTY, - OLE_ERROR_SIZE, - OLE_ERROR_DRIVE, - OLE_ERROR_NETWORK, - OLE_ERROR_NAME, - OLE_ERROR_TEMPLATE, - OLE_ERROR_NEW, - OLE_ERROR_EDIT, - OLE_ERROR_OPEN, - OLE_ERROR_NOT_OPEN, - OLE_ERROR_LAUNCH, - OLE_ERROR_COMM, - OLE_ERROR_TERMINATE, - OLE_ERROR_COMMAND, - OLE_ERROR_SHOW, - OLE_ERROR_DOVERB, - OLE_ERROR_ADVISE_NATIVE, - OLE_ERROR_ADVISE_PICT, - OLE_ERROR_ADVISE_RENAME, - OLE_ERROR_POKE_NATIVE, - OLE_ERROR_REQUEST_NATIVE, - OLE_ERROR_REQUEST_PICT, - OLE_ERROR_SERVER_BLOCKED, - OLE_ERROR_REGISTRATION, - OLE_ERROR_ALREADY_REGISTERED, - OLE_ERROR_TASK, - OLE_ERROR_OUTOFDATE, - OLE_ERROR_CANT_UPDATE_CLIENT, - OLE_ERROR_UPDATE, - OLE_ERROR_SETDATA_FORMAT, - OLE_ERROR_STATIC_FROM_OTHER_OS, - OLE_WARN_DELETE_DATA = 1000 -} OLESTATUS; - -typedef enum -{ - olerender_none, - olerender_draw, - olerender_format -} OLEOPT_RENDER; - -typedef enum -{ - oleupdate_always, - oleupdate_onsave, - oleupdate_oncall, - oleupdate_onclose -} OLEOPT_UPDATE; - -typedef enum { - OLE_NONE, /* none */ - OLE_DELETE, /* delete object */ - OLE_LNKPASTE, /* link paste */ - OLE_EMBPASTE, /* paste(and update) */ - OLE_SHOW, - OLE_RUN, - OLE_ACTIVATE, - OLE_UPDATE, - OLE_CLOSE, - OLE_RECONNECT, - OLE_SETUPDATEOPTIONS, - OLE_SERVERRUNLAUNCH, /* unlaunch (terminate?) server */ - OLE_LOADFROMSTREAM, /* (auto reconnect) */ - OLE_SETDATA, /* OleSetData */ - OLE_REQUESTDATA, /* OleRequestData */ - OLE_OTHER, - OLE_CREATE, - OLE_CREATEFROMTEMPLATE, - OLE_CREATELINKFROMFILE, - OLE_COPYFROMLNK, - OLE_CREATREFROMFILE, - OLE_CREATEINVISIBLE -} OLE_RELEASE_METHOD; - -typedef LONG LHCLIENTDOC; -typedef struct _OLEOBJECT *_LPOLEOBJECT; -typedef struct _OLECLIENT *LPOLECLIENT; -typedef LONG OLECLIPFORMAT;/* dunno about this type, please change/add */ -typedef OLEOPT_UPDATE *LPOLEOPT_UPDATE; -typedef LPCSTR LPCOLESTR16; - -struct _OLESTREAM; - typedef struct _OLEOBJECTVTBL16 { void CALLBACK *(*QueryProtocol)(_LPOLEOBJECT,LPCOLESTR16); OLESTATUS (CALLBACK *Release)(_LPOLEOBJECT); diff --git a/dlls/olecli32/olecli_main.c b/dlls/olecli32/olecli_main.c index a36cb72a3e1..7abd4383727 100644 --- a/dlls/olecli32/olecli_main.c +++ b/dlls/olecli32/olecli_main.c @@ -31,120 +31,11 @@ #include "wingdi.h" #include "wownt32.h" #include "objbase.h" +#include "olecli.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); -typedef enum -{ - OLE_OK, - OLE_WAIT_FOR_RELEASE, - OLE_BUSY, - OLE_ERROR_PROTECT_ONLY, - OLE_ERROR_MEMORY, - OLE_ERROR_STREAM, - OLE_ERROR_STATIC, - OLE_ERROR_BLANK, - OLE_ERROR_DRAW, - OLE_ERROR_METAFILE, - OLE_ERROR_ABORT, - OLE_ERROR_CLIPBOARD, - OLE_ERROR_FORMAT, - OLE_ERROR_OBJECT, - OLE_ERROR_OPTION, - OLE_ERROR_PROTOCOL, - OLE_ERROR_ADDRESS, - OLE_ERROR_NOT_EQUAL, - OLE_ERROR_HANDLE, - OLE_ERROR_GENERIC, - OLE_ERROR_CLASS, - OLE_ERROR_SYNTAX, - OLE_ERROR_DATATYPE, - OLE_ERROR_PALETTE, - OLE_ERROR_NOT_LINK, - OLE_ERROR_NOT_EMPTY, - OLE_ERROR_SIZE, - OLE_ERROR_DRIVE, - OLE_ERROR_NETWORK, - OLE_ERROR_NAME, - OLE_ERROR_TEMPLATE, - OLE_ERROR_NEW, - OLE_ERROR_EDIT, - OLE_ERROR_OPEN, - OLE_ERROR_NOT_OPEN, - OLE_ERROR_LAUNCH, - OLE_ERROR_COMM, - OLE_ERROR_TERMINATE, - OLE_ERROR_COMMAND, - OLE_ERROR_SHOW, - OLE_ERROR_DOVERB, - OLE_ERROR_ADVISE_NATIVE, - OLE_ERROR_ADVISE_PICT, - OLE_ERROR_ADVISE_RENAME, - OLE_ERROR_POKE_NATIVE, - OLE_ERROR_REQUEST_NATIVE, - OLE_ERROR_REQUEST_PICT, - OLE_ERROR_SERVER_BLOCKED, - OLE_ERROR_REGISTRATION, - OLE_ERROR_ALREADY_REGISTERED, - OLE_ERROR_TASK, - OLE_ERROR_OUTOFDATE, - OLE_ERROR_CANT_UPDATE_CLIENT, - OLE_ERROR_UPDATE, - OLE_ERROR_SETDATA_FORMAT, - OLE_ERROR_STATIC_FROM_OTHER_OS, - OLE_WARN_DELETE_DATA = 1000 -} OLESTATUS; - -typedef enum -{ - olerender_none, - olerender_draw, - olerender_format -} OLEOPT_RENDER; - -typedef enum -{ - oleupdate_always, - oleupdate_onsave, - oleupdate_oncall, - oleupdate_onclose -} OLEOPT_UPDATE; - -typedef enum { - OLE_NONE, /* none */ - OLE_DELETE, /* delete object */ - OLE_LNKPASTE, /* link paste */ - OLE_EMBPASTE, /* paste(and update) */ - OLE_SHOW, - OLE_RUN, - OLE_ACTIVATE, - OLE_UPDATE, - OLE_CLOSE, - OLE_RECONNECT, - OLE_SETUPDATEOPTIONS, - OLE_SERVERRUNLAUNCH, /* unlaunch (terminate?) server */ - OLE_LOADFROMSTREAM, /* (auto reconnect) */ - OLE_SETDATA, /* OleSetData */ - OLE_REQUESTDATA, /* OleRequestData */ - OLE_OTHER, - OLE_CREATE, - OLE_CREATEFROMTEMPLATE, - OLE_CREATELINKFROMFILE, - OLE_COPYFROMLNK, - OLE_CREATREFROMFILE, - OLE_CREATEINVISIBLE -} OLE_RELEASE_METHOD; - -typedef LONG LHCLIENTDOC; -typedef struct _OLEOBJECT *_LPOLEOBJECT; -typedef struct _OLECLIENT *LPOLECLIENT; -typedef LONG OLECLIPFORMAT;/* dunno about this type, please change/add */ -typedef OLEOPT_UPDATE *LPOLEOPT_UPDATE; -typedef LPCSTR LPCOLESTR16; - -struct _OLESTREAM; - typedef struct _OLEOBJECTVTBL { void * (CALLBACK *QueryProtocol)(_LPOLEOBJECT,LPCOLESTR16); OLESTATUS (CALLBACK *Release)(_LPOLEOBJECT); diff --git a/dlls/pdh/pdh_main.c b/dlls/pdh/pdh_main.c index a7aa21b6b7b..d78af4a433c 100644 --- a/dlls/pdh/pdh_main.c +++ b/dlls/pdh/pdh_main.c @@ -873,7 +873,7 @@ PDH_STATUS WINAPI PdhLookupPerfNameByIndexW( LPCWSTR machine, DWORD index, LPWST return PDH_CSTATUS_NO_MACHINE; } - if (!buffer && !size) return PDH_INVALID_ARGUMENT; + if (!buffer || !size) return PDH_INVALID_ARGUMENT; if (!index) return ERROR_SUCCESS; for (i = 0; i < sizeof(counter_sources) / sizeof(counter_sources[0]); i++) diff --git a/dlls/quartz/main.c b/dlls/quartz/main.c index 66b6f6a9d17..73c50622039 100644 --- a/dlls/quartz/main.c +++ b/dlls/quartz/main.c @@ -69,6 +69,7 @@ static const struct object_creation_info object_creation[] = { &CLSID_AviSplitter, AVISplitter_create }, { &CLSID_MPEG1Splitter, MPEGSplitter_create }, { &CLSID_VideoRenderer, VideoRenderer_create }, + { &CLSID_VideoRendererDefault, VideoRendererDefault_create }, { &CLSID_DSoundRender, DSoundRender_create }, { &CLSID_AVIDec, AVIDec_create }, { &CLSID_SystemClock, &QUARTZ_CreateSystemClock }, diff --git a/dlls/quartz/quartz_private.h b/dlls/quartz/quartz_private.h index a483f2a9aad..ebb6a027432 100644 --- a/dlls/quartz/quartz_private.h +++ b/dlls/quartz/quartz_private.h @@ -52,6 +52,7 @@ HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv); +HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT QUARTZ_CreateSystemClock(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv); HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv); diff --git a/dlls/quartz/regsvr.c b/dlls/quartz/regsvr.c index 8b93601afaa..98fd0bc5a29 100644 --- a/dlls/quartz/regsvr.c +++ b/dlls/quartz/regsvr.c @@ -861,6 +861,12 @@ static struct regsvr_coclass const coclass_list[] = { "quartz.dll", "Both" }, + { &CLSID_VideoRendererDefault, + "Default Video Renderer", + NULL, + "quartz.dll", + "Both" + }, { &CLSID_ACMWrapper, "ACM wrapper", NULL, @@ -1075,6 +1081,18 @@ static struct regsvr_filter const filter_list[] = { { 0xFFFFFFFF }, } }, + { &CLSID_VideoRendererDefault, + &CLSID_LegacyAmFilterCategory, + {'V','i','d','e','o',' ','R','e','n','d','e','r','e','r',0}, + 0x800000, + { { REG_PINFLAG_B_RENDERER, + { { &MEDIATYPE_Video, &GUID_NULL }, + { NULL } + }, + }, + { 0xFFFFFFFF }, + } + }, { &CLSID_AVIDec, &CLSID_LegacyAmFilterCategory, {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0}, diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c index 28f527c923d..ec16a4cb262 100644 --- a/dlls/quartz/videorenderer.c +++ b/dlls/quartz/videorenderer.c @@ -488,6 +488,12 @@ HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) return hr; } +HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv) +{ + /* TODO: Attenmpt to use the VMR-7 renderer instead when possible */ + return VideoRenderer_create(pUnkOuter, ppv); +} + static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv) { ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface); diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c index 2337107172b..3f0604eb7e7 100644 --- a/dlls/riched20/caret.c +++ b/dlls/riched20/caret.c @@ -393,18 +393,20 @@ ME_InternalInsertTextFromCursor(ME_TextEditor *editor, int nCursor, } -/* FIXME this is temporary, just to have something to test how bad graphics handler is */ -void ME_InsertGraphicsFromCursor(ME_TextEditor *editor, int nCursor) +void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor) { - ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor); - WCHAR space = ' '; + ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor); + ME_DisplayItem *di; + WCHAR space = ' '; /* FIXME no no no */ if (ME_IsSelection(editor)) ME_DeleteSelection(editor); - ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle, - MERF_GRAPHICS); + di = ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, pStyle, + MERF_GRAPHICS); + di->member.run.ole_obj = ALLOC_OBJ(*reo); + ME_CopyReObject(di->member.run.ole_obj, reo); ME_SendSelChange(editor); } diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 705c5a1c220..6aa21a7de6e 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -4,6 +4,7 @@ * Copyright 2004 by Krzysztof Foltman * Copyright 2005 by Cihan Altinay * Copyright 2005 by Phil Krylov + * Copyright 2008 Eric Pouech * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -506,6 +507,148 @@ static void ME_RTFParAttrHook(RTF_Info *info) if (fmt.cTabCount < MAX_TAB_STOPS) fmt.rgxTabs[fmt.cTabCount++] = info->rtfParam; break; + case rtfKeep: + fmt.dwMask = PFM_KEEP; + fmt.wEffects = PFE_KEEP; + break; + case rtfNoWidowControl: + fmt.dwMask = PFM_NOWIDOWCONTROL; + fmt.wEffects = PFE_NOWIDOWCONTROL; + break; + case rtfKeepNext: + fmt.dwMask = PFM_KEEPNEXT; + fmt.wEffects = PFE_KEEPNEXT; + break; + case rtfSpaceAfter: + fmt.dwMask = PFM_SPACEAFTER; + fmt.dySpaceAfter = info->rtfParam; + break; + case rtfSpaceBefore: + fmt.dwMask = PFM_SPACEBEFORE; + fmt.dySpaceBefore = info->rtfParam; + break; + case rtfSpaceBetween: + fmt.dwMask = PFM_LINESPACING; + if ((int)info->rtfParam > 0) + { + fmt.dyLineSpacing = info->rtfParam; + fmt.bLineSpacingRule = 3; + } + else + { + fmt.dyLineSpacing = info->rtfParam; + fmt.bLineSpacingRule = 4; + } + case rtfSpaceMultiply: + fmt.dwMask = PFM_LINESPACING; + fmt.dyLineSpacing = info->rtfParam * 20; + fmt.bLineSpacingRule = 5; + break; + case rtfParBullet: + fmt.dwMask = PFM_NUMBERING; + fmt.wNumbering = PFN_BULLET; + break; + case rtfParSimple: + fmt.dwMask = PFM_NUMBERING; + fmt.wNumbering = 2; /* FIXME: MSDN says it's not used ?? */ + break; + case rtfParNumDecimal: + fmt.dwMask = PFM_NUMBERING; + fmt.wNumbering = 2; /* FIXME: MSDN says it's not used ?? */ + break; + case rtfParNumIndent: + fmt.dwMask = PFM_NUMBERINGTAB; + fmt.wNumberingTab = info->rtfParam; + break; + case rtfParNumStartAt: + fmt.dwMask = PFM_NUMBERINGSTART; + fmt.wNumberingStart = info->rtfParam; + break; + case rtfBorderLeft: + ME_GetSelectionParaFormat(info->editor, &fmt); + if (!(fmt.dwMask & PFM_BORDER)) + { + fmt.dwMask |= PFM_BORDER; + fmt.wBorderSpace = 0; + fmt.wBorderWidth = 1; + fmt.wBorders = 0; + } + fmt.wBorders |= 1; + break; + case rtfBorderRight: + ME_GetSelectionParaFormat(info->editor, &fmt); + if (!(fmt.dwMask & PFM_BORDER)) + { + fmt.dwMask |= PFM_BORDER; + fmt.wBorderSpace = 0; + fmt.wBorderWidth = 1; + fmt.wBorders = 0; + } + fmt.wBorders |= 2; + break; + case rtfBorderTop: + ME_GetSelectionParaFormat(info->editor, &fmt); + if (!(fmt.dwMask & PFM_BORDER)) + { + fmt.dwMask |= PFM_BORDER; + fmt.wBorderSpace = 0; + fmt.wBorderWidth = 1; + fmt.wBorders = 0; + } + fmt.wBorders |= 4; + break; + case rtfBorderBottom: + ME_GetSelectionParaFormat(info->editor, &fmt); + if (!(fmt.dwMask & PFM_BORDER)) + { + fmt.dwMask |= PFM_BORDER; + fmt.wBorderSpace = 0; + fmt.wBorderWidth = 1; + fmt.wBorders = 0; + } + fmt.wBorders |= 8; + break; + case rtfBorderSingle: + ME_GetSelectionParaFormat(info->editor, &fmt); + /* we assume that borders have been created before (RTF spec) */ + fmt.wBorders &= ~0x70; + fmt.wBorders |= 1 << 8; + break; + case rtfBorderThick: + ME_GetSelectionParaFormat(info->editor, &fmt); + /* we assume that borders have been created before (RTF spec) */ + fmt.wBorders &= ~0x70; + fmt.wBorders |= 2 << 8; + break; + case rtfBorderShadow: + ME_GetSelectionParaFormat(info->editor, &fmt); + /* we assume that borders have been created before (RTF spec) */ + fmt.wBorders &= ~0x70; + fmt.wBorders |= 10 << 8; + break; + case rtfBorderDouble: + ME_GetSelectionParaFormat(info->editor, &fmt); + /* we assume that borders have been created before (RTF spec) */ + fmt.wBorders &= ~0x70; + fmt.wBorders |= 7 << 8; + break; + case rtfBorderDot: + ME_GetSelectionParaFormat(info->editor, &fmt); + /* we assume that borders have been created before (RTF spec) */ + fmt.wBorders &= ~0x70; + fmt.wBorders |= 11 << 8; + break; + case rtfBorderWidth: + ME_GetSelectionParaFormat(info->editor, &fmt); + /* we assume that borders have been created before (RTF spec) */ + fmt.wBorders &= ~0x70; + fmt.wBorders |= ((info->rtfParam / 15) & 7) << 8; + break; + case rtfBorderSpace: + ME_GetSelectionParaFormat(info->editor, &fmt); + /* we assume that borders have been created before (RTF spec) */ + fmt.wBorderSpace = info->rtfParam; + break; } if (fmt.dwMask) { RTFFlushOutputBuffer(info); @@ -549,6 +692,204 @@ static void ME_RTFTblAttrHook(RTF_Info *info) } } +static BOOL ME_RTFInsertOleObject(RTF_Info *info, HENHMETAFILE h, const SIZEL* sz) +{ + LPOLEOBJECT lpObject = NULL; + LPSTORAGE lpStorage = NULL; + LPOLECLIENTSITE lpClientSite = NULL; + LPDATAOBJECT lpDataObject = NULL; + LPOLECACHE lpOleCache = NULL; + STGMEDIUM stgm; + FORMATETC fm; + CLSID clsid; + BOOL ret = FALSE; + DWORD conn; + + stgm.tymed = TYMED_ENHMF; + stgm.u.hEnhMetaFile = h; + stgm.pUnkForRelease = NULL; + + fm.cfFormat = CF_ENHMETAFILE; + fm.ptd = NULL; + fm.dwAspect = DVASPECT_CONTENT; + fm.lindex = -1; + fm.tymed = stgm.tymed; + + if (!info->lpRichEditOle) + { + CreateIRichEditOle(info->editor, (VOID**)&info->lpRichEditOle); + } + + if (OleCreateDefaultHandler(&CLSID_NULL, NULL, &IID_IOleObject, (void**)&lpObject) == S_OK && +#if 0 + /* FIXME: enable it when rich-edit properly implements this method */ + IRichEditOle_GetClientSite(info->lpRichEditOle, &lpClientSite) == S_OK && + IOleObject_SetClientSite(lpObject, lpClientSite) == S_OK && +#endif + IOleObject_GetUserClassID(lpObject, &clsid) == S_OK && + IOleObject_QueryInterface(lpObject, &IID_IOleCache, (void**)&lpOleCache) == S_OK && + IOleCache_Cache(lpOleCache, &fm, 0, &conn) == S_OK && + IOleObject_QueryInterface(lpObject, &IID_IDataObject, (void**)&lpDataObject) == S_OK && + IDataObject_SetData(lpDataObject, &fm, &stgm, TRUE) == S_OK) + { + REOBJECT reobject; + + reobject.cbStruct = sizeof(reobject); + reobject.cp = REO_CP_SELECTION; + reobject.clsid = clsid; + reobject.poleobj = lpObject; + reobject.pstg = lpStorage; + reobject.polesite = lpClientSite; + /* convert from twips to .01 mm */ + reobject.sizel.cx = MulDiv(sz->cx, 254, 144); + reobject.sizel.cy = MulDiv(sz->cy, 254, 144); + reobject.dvaspect = DVASPECT_CONTENT; + reobject.dwFlags = 0; /* FIXME */ + reobject.dwUser = 0; + + /* FIXME: could be simpler */ + ret = IRichEditOle_InsertObject(info->lpRichEditOle, &reobject) == S_OK; + } + + if (lpObject) IOleObject_Release(lpObject); + if (lpClientSite) IOleClientSite_Release(lpClientSite); + if (lpStorage) IStorage_Release(lpStorage); + if (lpDataObject) IDataObject_Release(lpDataObject); + if (lpOleCache) IOleCache_Release(lpOleCache); + + return ret; +} + +static void ME_RTFReadPictGroup(RTF_Info *info) +{ + SIZEL sz; + BYTE* buffer = NULL; + unsigned bufsz, bufidx; + BOOL flip; + BYTE val; + METAFILEPICT mfp; + HENHMETAFILE hemf; + + RTFGetToken (info); + if (info->rtfClass == rtfEOF) + return; + mfp.mm = MM_TEXT; + /* fetch picture type */ + if (RTFCheckMM (info, rtfPictAttr, rtfWinMetafile)) + { + mfp.mm = info->rtfParam; + } + else + { + FIXME("%d %d\n", info->rtfMajor, info->rtfMinor); + goto skip_group; + } + sz.cx = sz.cy = 0; + /* fetch picture attributes */ + for (;;) + { + RTFGetToken (info); + if (info->rtfClass == rtfEOF) + return; + if (info->rtfClass == rtfText) + break; + if (!RTFCheckCM (info, rtfControl, rtfPictAttr)) + { + ERR("Expected picture attribute (%d %d)\n", + info->rtfClass, info->rtfMajor); + goto skip_group; + } + else if (RTFCheckMM (info, rtfPictAttr, rtfPicWid)) + mfp.xExt = info->rtfParam; + else if (RTFCheckMM (info, rtfPictAttr, rtfPicHt)) + mfp.yExt = info->rtfParam; + else if (RTFCheckMM (info, rtfPictAttr, rtfPicGoalWid)) + sz.cx = info->rtfParam; + else if (RTFCheckMM (info, rtfPictAttr, rtfPicGoalHt)) + sz.cy = info->rtfParam; + else + FIXME("Non supported attribute: %d %d %d\n", info->rtfClass, info->rtfMajor, info->rtfMinor); + } + /* fetch picture data */ + bufsz = 1024; + bufidx = 0; + buffer = HeapAlloc(GetProcessHeap(), 0, bufsz); + val = info->rtfMajor; + for (flip = TRUE;; flip = !flip) + { + RTFGetToken (info); + if (info->rtfClass == rtfEOF) + { + HeapFree(GetProcessHeap(), 0, buffer); + return; /* Warn ?? */ + } + if (RTFCheckCM(info, rtfGroup, rtfEndGroup)) + break; + if (info->rtfClass != rtfText) goto skip_group; + if (flip) + { + if (bufidx >= bufsz && + !(buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, bufsz += 1024))) + goto skip_group; + buffer[bufidx++] = RTFCharToHex(val) * 16 + RTFCharToHex(info->rtfMajor); + } + else + val = info->rtfMajor; + } + if (flip) FIXME("wrong hex string\n"); + + if ((hemf = SetWinMetaFileBits(bufidx, buffer, NULL, &mfp))) + ME_RTFInsertOleObject(info, hemf, &sz); + HeapFree(GetProcessHeap(), 0, buffer); + RTFRouteToken (info); /* feed "}" back to router */ + return; +skip_group: + HeapFree(GetProcessHeap(), 0, buffer); + RTFSkipGroup(info); + RTFRouteToken(info); /* feed "}" back to router */ +} + +/* for now, lookup the \result part and use it, whatever the object */ +static void ME_RTFReadObjectGroup(RTF_Info *info) +{ + for (;;) + { + RTFGetToken (info); + if (info->rtfClass == rtfEOF) + return; + if (RTFCheckCM(info, rtfGroup, rtfEndGroup)) + break; + if (RTFCheckCM(info, rtfGroup, rtfBeginGroup)) + { + RTFGetToken (info); + if (info->rtfClass == rtfEOF) + return; + if (RTFCheckCMM(info, rtfControl, rtfDestination, rtfObjResult)) + { + int level = 1; + + while (RTFGetToken (info) != rtfEOF) + { + if (info->rtfClass == rtfGroup) + { + if (info->rtfMajor == rtfBeginGroup) level++; + else if (info->rtfMajor == rtfEndGroup && --level < 0) break; + } + RTFRouteToken(info); + } + } + else RTFSkipGroup(info); + continue; + } + if (!RTFCheckCM (info, rtfControl, rtfObjAttr)) + { + FIXME("Non supported attribute: %d %d %d\n", info->rtfClass, info->rtfMajor, info->rtfMinor); + return; + } + } + RTFRouteToken(info); /* feed "}" back to router */ +} + static void ME_RTFReadHook(RTF_Info *info) { switch(info->rtfClass) { @@ -687,12 +1028,16 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre WriterInit(&parser); RTFInit(&parser); RTFSetReadHook(&parser, ME_RTFReadHook); + RTFSetDestinationCallback(&parser, rtfPict, ME_RTFReadPictGroup); + RTFSetDestinationCallback(&parser, rtfObject, ME_RTFReadObjectGroup); BeginFile(&parser); - + /* do the parsing */ RTFRead(&parser); RTFFlushOutputBuffer(&parser); RTFDestroy(&parser); + if (parser.lpRichEditOle) + IRichEditOle_Release(parser.lpRichEditOle); style = parser.style; } @@ -2081,7 +2426,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ex.flags = GT_USECRLF; ex.codepage = unicode ? 1200 : CP_ACP; ex.lpDefaultChar = NULL; - ex.lpUsedDefaultChar = NULL; + ex.lpUsedDefChar = NULL; rc = RichEditWndProc_common(hWnd, EM_GETTEXTEX, (WPARAM)&ex, unicode ? (LPARAM)bufferW : (LPARAM)bufferA, unicode); if (unicode) @@ -2135,7 +2480,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, buffer = heap_alloc((crlfmul*nCount + 1) * sizeof(WCHAR)); buflen = ME_GetTextW(editor, buffer, nStart, nCount, ex->flags & GT_USECRLF); - rc = WideCharToMultiByte(ex->codepage, flags, buffer, -1, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefaultChar); + rc = WideCharToMultiByte(ex->codepage, flags, buffer, -1, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefChar); if (rc) rc--; /* do not count 0 terminator */ heap_free(buffer); diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 145dc912d3e..8b97a5561cf 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -149,7 +149,6 @@ ME_DisplayItem *ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style, const WCHAR *str, int len, int flags); void ME_CheckCharOffsets(ME_TextEditor *editor); void ME_PropagateCharOffset(ME_DisplayItem *p, int shift); -void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize); int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run); /* this one accounts for 1/2 char tolerance */ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run); @@ -201,7 +200,7 @@ int ME_CountParagraphsBetween(ME_TextEditor *editor, int from, int to); BOOL ME_IsSelection(ME_TextEditor *editor); void ME_DeleteSelection(ME_TextEditor *editor); void ME_SendSelChange(ME_TextEditor *editor); -void ME_InsertGraphicsFromCursor(ME_TextEditor *editor, int nCursor); +void ME_InsertOLEFromCursor(ME_TextEditor *editor, const REOBJECT* reo, int nCursor); void ME_InsertTableCellFromCursor(ME_TextEditor *editor, int nCursor); void ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars); int ME_GetTextLength(ME_TextEditor *editor); @@ -259,7 +258,11 @@ int ME_GetParaBorderWidth(ME_TextEditor *editor, int); int ME_GetParaLineSpace(ME_Context *c, ME_Paragraph*); /* richole.c */ -extern LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *); +LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *); +void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run* run, ME_Paragraph *para, BOOL selected); +void ME_GetOLEObjectSize(ME_Context *c, ME_Run *run, SIZE *pSize); +void ME_CopyReObject(REOBJECT* dst, const REOBJECT* src); +void ME_DeleteReObject(REOBJECT* reo); /* wintest.c */ diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index aa7fd6b2ba0..92dbab4742b 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -145,6 +145,7 @@ typedef struct tagME_Run int nAscent, nDescent; /* pixels above/below baseline */ POINT pt; /* relative to para's position */ struct tagME_TableCell *pCell; /* for MERF_CELL: points to respective cell in ME_Paragraph */ + REOBJECT *ole_obj; /* FIXME: should be a union with strText (at least) */ } ME_Run; typedef struct tagME_Document { diff --git a/dlls/riched20/list.c b/dlls/riched20/list.c index ad7b4b659e4..14f9b178a40 100644 --- a/dlls/riched20/list.c +++ b/dlls/riched20/list.c @@ -115,6 +115,7 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item) { ME_DestroyTableCellList(item); } if (item->type==diRun || item->type == diUndoInsertRun) { + if (item->member.run.ole_obj) ME_DeleteReObject(item->member.run.ole_obj); ME_ReleaseStyle(item->member.run.style); ME_DestroyString(item->member.run.strText); } diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index 03a588c2aae..86876444669 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c @@ -246,34 +246,6 @@ static void ME_DebugWrite(HDC hDC, const POINT *pt, LPCWSTR szText) { SetTextColor(hDC, color); } -static void ME_DrawGraphics(ME_Context *c, int x, int y, ME_Run *run, - ME_Paragraph *para, BOOL selected) { - SIZE sz; - int xs, ys, xe, ye, h, ym, width, eyes; - ME_GetGraphicsSize(c->editor, run, &sz); - xs = run->pt.x; - ys = y-sz.cy; - xe = xs+sz.cx; - ye = y; - h = ye-ys; - ym = ys+h/4; - width = sz.cx; - eyes = width/8; - /* draw a smiling face :) */ - Ellipse(c->hDC, xs, ys, xe, ye); - Ellipse(c->hDC, xs+width/8, ym, x+width/8+eyes, ym+eyes); - Ellipse(c->hDC, xs+7*width/8-eyes, ym, xs+7*width/8, ym+eyes); - MoveToEx(c->hDC, xs+width/8, ys+3*h/4-eyes, NULL); - LineTo(c->hDC, xs+width/8, ys+3*h/4); - LineTo(c->hDC, xs+7*width/8, ys+3*h/4); - LineTo(c->hDC, xs+7*width/8, ys+3*h/4-eyes); - if (selected) - { - /* descent is usually (always?) 0 for graphics */ - PatBlt(c->hDC, x, y-run->nAscent, sz.cx, run->nAscent+run->nDescent, DSTINVERT); - } -} - static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Paragraph *para) { ME_Run *run = &rundi->member.run; @@ -299,7 +271,7 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa return; if (run->nFlags & MERF_GRAPHICS) - ME_DrawGraphics(c, x, y, run, para, (runofs >= nSelFrom) && (runofs < nSelTo)); + ME_DrawOLE(c, x, y, run, para, (runofs >= nSelFrom) && (runofs < nSelTo)); else { if (c->editor->cPasswordMask) diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c index 742323e0224..1509d4e1479 100644 --- a/dlls/riched20/richole.c +++ b/dlls/riched20/richole.c @@ -218,11 +218,18 @@ IRichEditOle_fnInPlaceDeactivate(IRichEditOle *me) } static HRESULT WINAPI -IRichEditOle_fnInsertObject(IRichEditOle *me, REOBJECT *lpreobject) +IRichEditOle_fnInsertObject(IRichEditOle *me, REOBJECT *reo) { IRichEditOleImpl *This = impl_from_IRichEditOle(me); - FIXME("stub %p\n",This); - return E_NOTIMPL; + TRACE("(%p,%p)\n", This, reo); + + if (reo->cbStruct < sizeof(*reo)) return STG_E_INVALIDPARAMETER; + if (reo->poleobj) IOleObject_AddRef(reo->poleobj); + if (reo->pstg) IStorage_AddRef(reo->pstg); + if (reo->polesite) IOleClientSite_AddRef(reo->polesite); + + ME_InsertOLEFromCursor(This->editor, reo, 0); + return S_OK; } static HRESULT WINAPI IRichEditOle_fnSaveCompleted(IRichEditOle *me, LONG iob, @@ -542,3 +549,204 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) return 1; } + +static void convert_sizel(ME_Context *c, const SIZEL* szl, SIZE* sz) +{ + /* sizel is in .01 millimeters, sz in pixels */ + sz->cx = MulDiv(szl->cx, c->dpi.cx, 2540); + sz->cy = MulDiv(szl->cy, c->dpi.cy, 2540); +} + +/****************************************************************************** + * ME_GetOLEObjectSize + * + * Sets run extent for OLE objects. + */ +void ME_GetOLEObjectSize(ME_Context *c, ME_Run *run, SIZE *pSize) +{ + IDataObject* ido; + FORMATETC fmt; + STGMEDIUM stgm; + DIBSECTION dibsect; + ENHMETAHEADER emh; + + assert(run->nFlags & MERF_GRAPHICS); + assert(run->ole_obj); + + if (run->ole_obj->sizel.cx != 0 || run->ole_obj->sizel.cy != 0) + { + convert_sizel(c, &run->ole_obj->sizel, pSize); + return; + } + + IOleObject_QueryInterface(run->ole_obj->poleobj, &IID_IDataObject, (void**)&ido); + fmt.cfFormat = CF_BITMAP; + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_GDI; + if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK) + { + fmt.cfFormat = CF_ENHMETAFILE; + fmt.tymed = TYMED_ENHMF; + if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK) + { + FIXME("unsupported format\n"); + pSize->cx = pSize->cy = 0; + IDataObject_Release(ido); + return; + } + } + + switch (stgm.tymed) + { + case TYMED_GDI: + GetObjectW(stgm.u.hBitmap, sizeof(dibsect), &dibsect); + pSize->cx = dibsect.dsBm.bmWidth; + pSize->cy = dibsect.dsBm.bmHeight; + if (!stgm.pUnkForRelease) DeleteObject(stgm.u.hBitmap); + break; + case TYMED_ENHMF: + GetEnhMetaFileHeader(stgm.u.hEnhMetaFile, sizeof(emh), &emh); + pSize->cx = emh.rclBounds.right - emh.rclBounds.left; + pSize->cy = emh.rclBounds.bottom - emh.rclBounds.top; + if (!stgm.pUnkForRelease) DeleteEnhMetaFile(stgm.u.hEnhMetaFile); + break; + default: + FIXME("Unsupported tymed %d\n", stgm.tymed); + break; + } + IDataObject_Release(ido); + if (c->editor->nZoomNumerator != 0) + { + pSize->cx = MulDiv(pSize->cx, c->editor->nZoomNumerator, c->editor->nZoomDenominator); + pSize->cy = MulDiv(pSize->cy, c->editor->nZoomNumerator, c->editor->nZoomDenominator); + } +} + +void ME_DrawOLE(ME_Context *c, int x, int y, ME_Run *run, + ME_Paragraph *para, BOOL selected) +{ + IDataObject* ido; + FORMATETC fmt; + STGMEDIUM stgm; + DIBSECTION dibsect; + ENHMETAHEADER emh; + HDC hMemDC; + SIZE sz; + BOOL has_size; + + assert(run->nFlags & MERF_GRAPHICS); + assert(run->ole_obj); + if (IOleObject_QueryInterface(run->ole_obj->poleobj, &IID_IDataObject, (void**)&ido) != S_OK) + { + FIXME("Couldn't get interface\n"); + return; + } + has_size = run->ole_obj->sizel.cx != 0 || run->ole_obj->sizel.cy != 0; + fmt.cfFormat = CF_BITMAP; + fmt.ptd = NULL; + fmt.dwAspect = DVASPECT_CONTENT; + fmt.lindex = -1; + fmt.tymed = TYMED_GDI; + if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK) + { + fmt.cfFormat = CF_ENHMETAFILE; + fmt.tymed = TYMED_ENHMF; + if (IDataObject_GetData(ido, &fmt, &stgm) != S_OK) + { + FIXME("Couldn't get storage medium\n"); + IDataObject_Release(ido); + return; + } + } + switch (stgm.tymed) + { + case TYMED_GDI: + GetObjectW(stgm.u.hBitmap, sizeof(dibsect), &dibsect); + hMemDC = CreateCompatibleDC(c->hDC); + SelectObject(hMemDC, stgm.u.hBitmap); + if (!has_size && c->editor->nZoomNumerator == 0) + { + sz.cx = dibsect.dsBm.bmWidth; + sz.cy = dibsect.dsBm.bmHeight; + BitBlt(c->hDC, x, y - dibsect.dsBm.bmHeight, + dibsect.dsBm.bmWidth, dibsect.dsBm.bmHeight, + hMemDC, 0, 0, SRCCOPY); + } + else + { + if (has_size) + { + convert_sizel(c, &run->ole_obj->sizel, &sz); + } + else + { + sz.cy = MulDiv(dibsect.dsBm.bmWidth, + c->editor->nZoomNumerator, c->editor->nZoomDenominator); + sz.cx = MulDiv(dibsect.dsBm.bmHeight, + c->editor->nZoomNumerator, c->editor->nZoomDenominator); + } + StretchBlt(c->hDC, x, y - sz.cy, sz.cx, sz.cy, + hMemDC, 0, 0, dibsect.dsBm.bmWidth, dibsect.dsBm.bmHeight, SRCCOPY); + } + if (!stgm.pUnkForRelease) DeleteObject(stgm.u.hBitmap); + break; + case TYMED_ENHMF: + GetEnhMetaFileHeader(stgm.u.hEnhMetaFile, sizeof(emh), &emh); + if (!has_size && c->editor->nZoomNumerator == 0) + { + sz.cy = emh.rclBounds.bottom - emh.rclBounds.top; + sz.cx = emh.rclBounds.right - emh.rclBounds.left; + } + else + { + if (has_size) + { + convert_sizel(c, &run->ole_obj->sizel, &sz); + } + else + { + sz.cy = MulDiv(emh.rclBounds.bottom - emh.rclBounds.top, + c->editor->nZoomNumerator, c->editor->nZoomDenominator); + sz.cx = MulDiv(emh.rclBounds.right - emh.rclBounds.left, + c->editor->nZoomNumerator, c->editor->nZoomDenominator); + } + } + { + RECT rc; + + rc.left = x; + rc.top = y - sz.cy; + rc.right = x + sz.cx; + rc.bottom = y; + PlayEnhMetaFile(c->hDC, stgm.u.hEnhMetaFile, &rc); + } + if (!stgm.pUnkForRelease) DeleteEnhMetaFile(stgm.u.hEnhMetaFile); + break; + default: + FIXME("Unsupported tymed %d\n", stgm.tymed); + selected = FALSE; + break; + } + if (selected && !c->editor->bHideSelection) + PatBlt(c->hDC, x, y - sz.cy, sz.cx, sz.cy, DSTINVERT); + IDataObject_Release(ido); +} + +void ME_DeleteReObject(REOBJECT* reo) +{ + if (reo->poleobj) IOleObject_Release(reo->poleobj); + if (reo->pstg) IStorage_Release(reo->pstg); + if (reo->polesite) IOleClientSite_Release(reo->polesite); + FREE_OBJ(reo); +} + +void ME_CopyReObject(REOBJECT* dst, const REOBJECT* src) +{ + *dst = *src; + + if (dst->poleobj) IOleObject_AddRef(dst->poleobj); + if (dst->pstg) IStorage_AddRef(dst->pstg); + if (dst->polesite) IOleClientSite_AddRef(dst->polesite); +} diff --git a/dlls/riched20/rtf.h b/dlls/riched20/rtf.h index 5a1251533a3..3a9c235cd47 100644 --- a/dlls/riched20/rtf.h +++ b/dlls/riched20/rtf.h @@ -1103,6 +1103,7 @@ struct _RTF_Info { RTFState stack[maxStack]; int stackTop; BOOL styleChanged; + LPRICHEDITOLE lpRichEditOle; }; diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c index 2da891e7851..9ed14d34445 100644 --- a/dlls/riched20/run.c +++ b/dlls/riched20/run.c @@ -359,6 +359,7 @@ ME_DisplayItem *ME_MakeRun(ME_Style *s, ME_String *strData, int nFlags) { ME_DisplayItem *item = ME_MakeDI(diRun); item->member.run.style = s; + item->member.run.ole_obj = NULL; item->member.run.strText = strData; item->member.run.nFlags = nFlags; item->member.run.nCharOfs = -1; @@ -468,19 +469,6 @@ void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run) } /****************************************************************************** - * ME_GetGraphicsSize - * - * Sets run extent for graphics runs. This functionality is just a placeholder - * for future OLE object support, and will be removed. - */ -void ME_GetGraphicsSize(ME_TextEditor *editor, ME_Run *run, SIZE *pSize) -{ - assert(run->nFlags & MERF_GRAPHICS); - pSize->cx = 64; - pSize->cy = 64; -} - -/****************************************************************************** * ME_CharFromPoint * * Returns a character position inside the run given a run-relative @@ -504,7 +492,7 @@ int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run) if (run->nFlags & MERF_GRAPHICS) { SIZE sz; - ME_GetGraphicsSize(c->editor, run, &sz); + ME_GetOLEObjectSize(c, run, &sz); if (cx < sz.cx) return 0; return 1; @@ -558,21 +546,22 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run) return 0; return 1; } + ME_InitContext(&c, editor, GetDC(editor->hWnd)); if (run->nFlags & MERF_GRAPHICS) { SIZE sz; - ME_GetGraphicsSize(editor, run, &sz); + ME_GetOLEObjectSize(&c, run, &sz); + ReleaseDC(editor->hWnd, c.hDC); if (cx < sz.cx/2) return 0; return 1; } - + if (editor->cPasswordMask) strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(run->strText)); else strRunText = run->strText; - ME_InitContext(&c, editor, GetDC(editor->hWnd)); hOldFont = ME_SelectStyleFont(&c, run->style); GetTextExtentExPointW(c.hDC, strRunText->szData, strRunText->nLen, cx, &fit, NULL, &sz); @@ -621,19 +610,20 @@ int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset) ME_String *strRunText; /* This could point to either the run's real text, or it's masked form in a password control */ + ME_InitContext(&c, editor, GetDC(editor->hWnd)); if (pRun->nFlags & MERF_GRAPHICS) { - if (!nOffset) return 0; - ME_GetGraphicsSize(editor, pRun, &size); - return 1; + if (nOffset) + ME_GetOLEObjectSize(&c, pRun, &size); + ReleaseDC(editor->hWnd, c.hDC); + return nOffset != 0; } if (editor->cPasswordMask) strRunText = ME_MakeStringR(editor->cPasswordMask,ME_StrVLen(pRun->strText)); else strRunText = pRun->strText; - - ME_InitContext(&c, editor, GetDC(editor->hWnd)); + ME_GetTextExtent(&c, strRunText->szData, nOffset, pRun->style, &size); ReleaseDC(editor->hWnd, c.hDC); if (editor->cPasswordMask) @@ -701,7 +691,7 @@ static SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run } if (run->nFlags & MERF_GRAPHICS) { - ME_GetGraphicsSize(c->editor, run, &size); + ME_GetOLEObjectSize(c, run, &size); if (size.cy > *pAscent) *pAscent = size.cy; /* descent is unchanged */ diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index 73f87fa595d..090eaad0320 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -1134,7 +1134,7 @@ static void test_EM_SETTEXTEX(void) getText.cb = MAX_BUF_LEN; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; setText.flags = 0; SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem1); @@ -1150,7 +1150,7 @@ static void test_EM_SETTEXTEX(void) getText.cb = MAX_BUF_LEN; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; setText.flags = 0; SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem2); SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf); @@ -1167,7 +1167,7 @@ static void test_EM_SETTEXTEX(void) getText.codepage = 1200; /* no constant for unicode */ getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; memset(buf, 0, MAX_BUF_LEN); SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf); ok(lstrcmpW(buf, TestItem2) == 0, @@ -1182,7 +1182,7 @@ static void test_EM_SETTEXTEX(void) getText.codepage = 1200; /* no constant for unicode */ getText.flags = GT_USECRLF; /* <-- asking for CR -> CRLF conversion */ getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; memset(buf, 0, MAX_BUF_LEN); SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf); ok(lstrcmpW(buf, TestItem1) == 0, @@ -1195,7 +1195,7 @@ static void test_EM_SETTEXTEX(void) getText.cb = MAX_BUF_LEN; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; setText.flags = 0; SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem3); SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf); @@ -1208,7 +1208,7 @@ static void test_EM_SETTEXTEX(void) getText.cb = MAX_BUF_LEN; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; setText.flags = 0; SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem3alt); SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf); @@ -1221,7 +1221,7 @@ static void test_EM_SETTEXTEX(void) getText.cb = MAX_BUF_LEN; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; setText.flags = 0; SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem4); SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf); @@ -1829,7 +1829,7 @@ static void test_EM_REPLACESEL(void) getText.codepage = CP_ACP; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buffer); ok(strcmp(buffer, "RichEdit1") == 0, "EM_GETTEXTEX results not what was set by EM_REPLACESEL\n"); @@ -1844,7 +1844,7 @@ static void test_EM_REPLACESEL(void) getText.codepage = CP_ACP; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buffer); ok(strcmp(buffer, "RichEdit1\r") == 0, "EM_GETTEXTEX returned incorrect string\n"); @@ -1873,7 +1873,7 @@ static void test_EM_REPLACESEL(void) getText.codepage = CP_ACP; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buffer); ok(strcmp(buffer, "RichEdit1\r") == 0, "EM_GETTEXTEX returned incorrect string\n"); @@ -1902,7 +1902,7 @@ static void test_EM_REPLACESEL(void) getText.codepage = CP_ACP; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buffer); ok(strcmp(buffer, "\r\r") == 0, "EM_GETTEXTEX returned incorrect string\n"); @@ -1921,7 +1921,7 @@ static void test_EM_REPLACESEL(void) getText.codepage = CP_ACP; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buffer); ok(strcmp(buffer, " ") == 0, "EM_GETTEXTEX returned incorrect string\n"); @@ -1940,7 +1940,7 @@ static void test_EM_REPLACESEL(void) getText.codepage = CP_ACP; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buffer); ok(strcmp(buffer, "\r\r\r \r\r\r") == 0, "EM_GETTEXTEX returned incorrect string\n"); @@ -1959,7 +1959,7 @@ static void test_EM_REPLACESEL(void) getText.codepage = CP_ACP; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buffer); ok(strcmp(buffer, " \r") == 0, "EM_GETTEXTEX returned incorrect string\n"); @@ -1978,7 +1978,7 @@ static void test_EM_REPLACESEL(void) getText.codepage = CP_ACP; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buffer); ok(strcmp(buffer, " \r\r") == 0, "EM_GETTEXTEX returned incorrect string\n"); @@ -1997,7 +1997,7 @@ static void test_EM_REPLACESEL(void) getText.codepage = CP_ACP; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buffer); ok(strcmp(buffer, "\rX\r\r\r") == 0, "EM_GETTEXTEX returned incorrect string\n"); @@ -2015,7 +2015,7 @@ static void test_EM_REPLACESEL(void) getText.codepage = CP_ACP; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buffer); ok(strcmp(buffer, "\r\r") == 0, "EM_GETTEXTEX returned incorrect string\n"); @@ -2034,7 +2034,7 @@ static void test_EM_REPLACESEL(void) getText.codepage = CP_ACP; getText.flags = GT_DEFAULT; getText.lpDefaultChar = NULL; - getText.lpUsedDefaultChar = NULL; + getText.lpUsedDefChar = NULL; SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buffer); ok(strcmp(buffer, "\r\r\r\r\r\r ") == 0, "EM_GETTEXTEX returned incorrect string\n"); diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c index d277e262192..12c8d30ba74 100644 --- a/dlls/riched20/undo.c +++ b/dlls/riched20/undo.c @@ -71,6 +71,12 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp CopyMemory(&pItem->member.run, &pdi->member.run, sizeof(ME_Run)); pItem->member.run.strText = ME_StrDup(pItem->member.run.strText); ME_AddRefStyle(pItem->member.run.style); + if (pdi->member.run.ole_obj) + { + pItem->member.run.ole_obj = ALLOC_OBJ(*pItem->member.run.ole_obj); + ME_CopyReObject(pItem->member.run.ole_obj, pdi->member.run.ole_obj); + } + else pItem->member.run.ole_obj = NULL; break; case diUndoSetCharFormat: case diUndoSetDefaultCharFormat: diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c index 4daf58efc95..1037cec6c26 100644 --- a/dlls/riched20/wrap.c +++ b/dlls/riched20/wrap.c @@ -293,8 +293,13 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p) wc->bOverflown = TRUE; return p; } - /* graphics or TAB - we can split before */ - if (run->nFlags & (MERF_GRAPHICS|MERF_TAB)) { + /* TAB: we can split before */ + if (run->nFlags & MERF_TAB) { + wc->bOverflown = TRUE; + return p; + } + /* graphics: we can split before, if run's width is smaller than row's width */ + if ((run->nFlags & MERF_GRAPHICS) && run->nWidth <= wc->nAvailWidth) { wc->bOverflown = TRUE; return p; } diff --git a/dlls/riched20/writer.c b/dlls/riched20/writer.c index 68088f7a15c..ff3f5ee9d0e 100644 --- a/dlls/riched20/writer.c +++ b/dlls/riched20/writer.c @@ -18,6 +18,9 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "config.h" +#include "wine/port.h" + #include "editor.h" #include "rtf.h" diff --git a/dlls/rpcrt4/rpc_message.c b/dlls/rpcrt4/rpc_message.c index de6f97dc6b3..068adf177f0 100644 --- a/dlls/rpcrt4/rpc_message.c +++ b/dlls/rpcrt4/rpc_message.c @@ -813,6 +813,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, void *payload = NULL; *Header = NULL; + pMsg->Buffer = NULL; TRACE("(%p, %p, %p)\n", Connection, Header, pMsg); @@ -869,14 +870,14 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, goto fail; } - if ((CurrentHeader->common.flags & RPC_FLG_FIRST) != first_flag) { + if (CurrentHeader->common.auth_len != auth_length) { WARN("auth_len header field changed from %ld to %d\n", - auth_length, (*Header)->common.auth_len); + auth_length, CurrentHeader->common.auth_len); status = RPC_S_PROTOCOL_ERROR; goto fail; } - if (((*Header)->common.flags & RPC_FLG_FIRST) != first_flag) { + if ((CurrentHeader->common.flags & RPC_FLG_FIRST) != first_flag) { TRACE("invalid packet flags\n"); status = RPC_S_PROTOCOL_ERROR; goto fail; @@ -964,6 +965,8 @@ fail: if (CurrentHeader != *Header) RPCRT4_FreeHeader(CurrentHeader); if (status != RPC_S_OK) { + I_RpcFree(pMsg->Buffer); + pMsg->Buffer = NULL; RPCRT4_FreeHeader(*Header); *Header = NULL; } diff --git a/dlls/rpcrt4/rpc_server.c b/dlls/rpcrt4/rpc_server.c index 35acbb771ac..9ffec507226 100644 --- a/dlls/rpcrt4/rpc_server.c +++ b/dlls/rpcrt4/rpc_server.c @@ -391,6 +391,7 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket)); if (!packet) { + I_RpcFree(msg->Buffer); HeapFree(GetProcessHeap(), 0, msg); break; } @@ -399,6 +400,7 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) packet->msg = msg; if (!QueueUserWorkItem(RPCRT4_worker_thread, packet, WT_EXECUTELONGFUNCTION)) { ERR("couldn't queue work item for worker thread, error was %d\n", GetLastError()); + I_RpcFree(msg->Buffer); HeapFree(GetProcessHeap(), 0, msg); HeapFree(GetProcessHeap(), 0, packet); break; diff --git a/dlls/rpcrt4/tests/rpc.c b/dlls/rpcrt4/tests/rpc.c index e92b05778c3..a95ff50967c 100644 --- a/dlls/rpcrt4/tests/rpc.c +++ b/dlls/rpcrt4/tests/rpc.c @@ -112,6 +112,7 @@ static void UuidConversionAndComparison(void) { ok( (UuidFromStringA((unsigned char*)str, &Uuid1) == RPC_S_INVALID_STRING_UUID), "Invalid UUID String\n" ); str[i2] = x; /* change it back so remaining tests are interesting. */ } + RpcStringFree((unsigned char **)&str); } /* Uuid to String to Uuid (wchar) */ @@ -132,6 +133,7 @@ static void UuidConversionAndComparison(void) { ok( (UuidFromStringW(wstr, &Uuid1) == RPC_S_INVALID_STRING_UUID), "Invalid UUID WString\n" ); wstr[i2] = wx; /* change it back so remaining tests are interesting. */ } + RpcStringFreeW(&wstr); } } @@ -323,6 +325,12 @@ static void test_towers(void) ret = TowerConstruct(&mapi_if_id, &ndr_syntax, "ncacn_ip_tcp", "135", "10.0.0.1", &tower); ok(ret == RPC_S_OK, "TowerConstruct failed with error %ld\n", ret); + if (ret == RPC_S_INVALID_RPC_PROTSEQ) + { + /* Windows Vista fails with this error and crashes if we continue */ + skip("TowerConstruct failed, we are most likely on Windows Vista\n"); + return; + } /* first check we have the right amount of data */ ok(tower->tower_length == sizeof(tower_data_tcp_ip1) || @@ -390,6 +398,12 @@ static void test_I_RpcMapWin32Status(void) { LONG win32status; RPC_STATUS rpc_status; + BOOL w2k3 = FALSE; + + /* Windows 2003 returns STATUS_UNSUCCESSFUL if given an unknown status */ + win32status = I_RpcMapWin32Status(9999); + if (win32status == STATUS_UNSUCCESSFUL) + w2k3 = TRUE; for (rpc_status = 0; rpc_status < 10000; rpc_status++) { @@ -397,6 +411,7 @@ static void test_I_RpcMapWin32Status(void) win32status = I_RpcMapWin32Status(rpc_status); switch (rpc_status) { + case ERROR_SUCCESS: expected_win32status = ERROR_SUCCESS; break; case ERROR_ACCESS_DENIED: expected_win32status = STATUS_ACCESS_DENIED; break; case ERROR_INVALID_HANDLE: expected_win32status = RPC_NT_SS_CONTEXT_MISMATCH; break; case ERROR_OUTOFMEMORY: expected_win32status = STATUS_NO_MEMORY; break; @@ -503,7 +518,11 @@ static void test_I_RpcMapWin32Status(void) case RPC_X_PIPE_EMPTY: expected_win32status = RPC_NT_PIPE_EMPTY; break; case ERROR_PASSWORD_MUST_CHANGE: expected_win32status = STATUS_PASSWORD_MUST_CHANGE; break; case ERROR_ACCOUNT_LOCKED_OUT: expected_win32status = STATUS_ACCOUNT_LOCKED_OUT; break; - default: expected_win32status = rpc_status; + default: + if (w2k3) + expected_win32status = STATUS_UNSUCCESSFUL; + else + expected_win32status = rpc_status; } ok(win32status == expected_win32status, "I_RpcMapWin32Status(%ld) should have returned 0x%x instead of 0x%x\n", rpc_status, expected_win32status, win32status); diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c index 425b20b98af..43c3ec2cd11 100644 --- a/dlls/rpcrt4/tests/server.c +++ b/dlls/rpcrt4/tests/server.c @@ -634,25 +634,21 @@ make_cmdline(char buffer[MAX_PATH], const char *test) sprintf(buffer, "%s server %s", progname, test); } -static int +static void run_client(const char *test) { char cmdline[MAX_PATH]; PROCESS_INFORMATION info; STARTUPINFOA startup; - DWORD exitcode; memset(&startup, 0, sizeof startup); startup.cb = sizeof startup; make_cmdline(cmdline, test); ok(CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); - ok(GetExitCodeProcess(info.hProcess, &exitcode), "GetExitCodeProcess\n"); + winetest_wait_child_process( info.hProcess ); ok(CloseHandle(info.hProcess), "CloseHandle\n"); ok(CloseHandle(info.hThread), "CloseHandle\n"); - - return exitcode == 0; } static void @@ -1208,10 +1204,10 @@ server(void) stop_event = CreateEvent(NULL, FALSE, FALSE, NULL); ok(stop_event != NULL, "CreateEvent failed\n"); - ok(run_client("tcp_basic"), "tcp_basic client test failed\n"); + run_client("tcp_basic"); ok(RPC_S_OK == RpcServerUseProtseqEp(np, 0, pipe, NULL), "RpcServerUseProtseqEp\n"); - ok(run_client("np_basic"), "np_basic client test failed\n"); + run_client("np_basic"); ok(WAIT_OBJECT_0 == WaitForSingleObject(stop_event, 60000), "WaitForSingleObject\n"); todo_wine { diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c index 1f0e0b29cdb..ded6df7c074 100644 --- a/dlls/rsaenh/rsaenh.c +++ b/dlls/rsaenh/rsaenh.c @@ -75,8 +75,7 @@ typedef struct tagCRYPTHASH #define RSAENH_MAX_BLOCK_SIZE 24 #define RSAENH_KEYSTATE_IDLE 0 #define RSAENH_KEYSTATE_ENCRYPTING 1 -#define RSAENH_KEYSTATE_DECRYPTING 2 -#define RSAENH_KEYSTATE_MASTERKEY 3 +#define RSAENH_KEYSTATE_MASTERKEY 2 typedef struct _RSAENH_SCHANNEL_INFO { SCHANNEL_ALG saEncAlg; @@ -2115,9 +2114,9 @@ BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, } if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE) - pCryptKey->dwState = RSAENH_KEYSTATE_DECRYPTING; + pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING; - if (pCryptKey->dwState != RSAENH_KEYSTATE_DECRYPTING) + if (pCryptKey->dwState != RSAENH_KEYSTATE_ENCRYPTING) { SetLastError(NTE_BAD_DATA); return FALSE; diff --git a/dlls/secur32/dispatcher.c b/dlls/secur32/dispatcher.c index 226de79ccab..400334610b9 100644 --- a/dlls/secur32/dispatcher.c +++ b/dlls/secur32/dispatcher.c @@ -116,6 +116,13 @@ SECURITY_STATUS fork_helper(PNegoHelper *new_helper, const char *prog, helper->com_buf_offset = 0; helper->session_key = NULL; helper->neg_flags = 0; + helper->crypt.ntlm.a4i = NULL; + helper->crypt.ntlm2.send_a4i = NULL; + helper->crypt.ntlm2.recv_a4i = NULL; + helper->crypt.ntlm2.send_sign_key = NULL; + helper->crypt.ntlm2.send_seal_key = NULL; + helper->crypt.ntlm2.recv_sign_key = NULL; + helper->crypt.ntlm2.recv_seal_key = NULL; helper->pipe_in = pipe_in[0]; fcntl( pipe_in[0], F_SETFD, 1 ); close(pipe_in[1]); diff --git a/dlls/secur32/ntlm.c b/dlls/secur32/ntlm.c index 3dbdd830af0..5b95d92b9fa 100644 --- a/dlls/secur32/ntlm.c +++ b/dlls/secur32/ntlm.c @@ -24,11 +24,13 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" +#include "wincred.h" #include "rpc.h" #include "sspi.h" #include "lm.h" #include "secur32_priv.h" #include "hmac_md5.h" +#include "wine/unicode.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ntlm); @@ -93,6 +95,42 @@ static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW( return ret; } +static char *ntlm_GetUsernameArg(LPCWSTR userW, INT userW_length) +{ + static const char username_arg[] = "--username="; + char *user; + int unixcp_size; + + unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, + userW, userW_length, NULL, 0, NULL, NULL) + sizeof(username_arg); + user = HeapAlloc(GetProcessHeap(), 0, unixcp_size); + if (!user) return NULL; + memcpy(user, username_arg, sizeof(username_arg) - 1); + WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, userW, userW_length, + user + sizeof(username_arg) - 1, + unixcp_size - sizeof(username_arg) + 1, NULL, NULL); + user[unixcp_size - 1] = '\0'; + return user; +} + +static char *ntlm_GetDomainArg(LPCWSTR domainW, INT domainW_length) +{ + static const char domain_arg[] = "--domain="; + char *domain; + int unixcp_size; + + unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, + domainW, domainW_length, NULL, 0, NULL, NULL) + sizeof(domain_arg); + domain = HeapAlloc(GetProcessHeap(), 0, unixcp_size); + if (!domain) return NULL; + memcpy(domain, domain_arg, sizeof(domain_arg) - 1); + WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, domainW, + domainW_length, domain + sizeof(domain_arg) - 1, + unixcp_size - sizeof(domain) + 1, NULL, NULL); + domain[unixcp_size - 1] = '\0'; + return domain; +} + /*********************************************************************** * AcquireCredentialsHandleW */ @@ -129,54 +167,6 @@ static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW( break; case SECPKG_CRED_OUTBOUND: { - static const char username_arg[] = "--username="; - static const char domain_arg[] = "--domain="; - int unixcp_size; - - if(pAuthData == NULL) - { - LPWKSTA_USER_INFO_1 ui = NULL; - NET_API_STATUS status; - - status = NetWkstaUserGetInfo(NULL, 1, (LPBYTE *)&ui); - if (status != NERR_Success || ui == NULL) - { - ret = SEC_E_NO_CREDENTIALS; - phCredential = NULL; - break; - } - - username = HeapAlloc(GetProcessHeap(), 0, - (lstrlenW(ui->wkui1_username)+1) * - sizeof(SEC_WCHAR)); - lstrcpyW(username, ui->wkui1_username); - - /* same for the domain */ - domain = HeapAlloc(GetProcessHeap(), 0, - (lstrlenW(ui->wkui1_logon_domain)+1) * - sizeof(SEC_WCHAR)); - lstrcpyW(domain, ui->wkui1_logon_domain); - NetApiBufferFree(ui); - } - else - { - PSEC_WINNT_AUTH_IDENTITY_W auth_data = - (PSEC_WINNT_AUTH_IDENTITY_W)pAuthData; - - /* Get username and domain from pAuthData */ - username = HeapAlloc(GetProcessHeap(), 0, - (auth_data->UserLength + 1) * sizeof(SEC_WCHAR)); - memcpy(username, auth_data->User, - auth_data->UserLength * sizeof(SEC_WCHAR)); - username[auth_data->UserLength] = '\0'; - - domain = HeapAlloc(GetProcessHeap(), 0, - (auth_data->DomainLength + 1) * sizeof(SEC_WCHAR)); - memcpy(domain, auth_data->Domain, - auth_data->DomainLength * sizeof(SEC_WCHAR)); - domain[auth_data->DomainLength] = '\0'; - } - ntlm_cred = HeapAlloc(GetProcessHeap(), 0, sizeof(*ntlm_cred)); if (!ntlm_cred) { @@ -184,31 +174,21 @@ static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW( break; } ntlm_cred->mode = NTLM_CLIENT; + ntlm_cred->username_arg = NULL; + ntlm_cred->domain_arg = NULL; ntlm_cred->password = NULL; ntlm_cred->pwlen = 0; - TRACE("Username is %s\n", debugstr_w(username)); - unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, - username, -1, NULL, 0, NULL, NULL) + sizeof(username_arg); - ntlm_cred->username_arg = HeapAlloc(GetProcessHeap(), 0, unixcp_size); - memcpy(ntlm_cred->username_arg, username_arg, sizeof(username_arg) - 1); - WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, username, -1, - ntlm_cred->username_arg + sizeof(username_arg) - 1, - unixcp_size - sizeof(username_arg) + 1, NULL, NULL); - - TRACE("Domain name is %s\n", debugstr_w(domain)); - unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, - domain, -1, NULL, 0, NULL, NULL) + sizeof(domain_arg); - ntlm_cred->domain_arg = HeapAlloc(GetProcessHeap(), 0, unixcp_size); - memcpy(ntlm_cred->domain_arg, domain_arg, sizeof(domain_arg) - 1); - WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, domain, - -1, ntlm_cred->domain_arg + sizeof(domain_arg) - 1, - unixcp_size - sizeof(domain) + 1, NULL, NULL); - if(pAuthData != NULL) { PSEC_WINNT_AUTH_IDENTITY_W auth_data = - (PSEC_WINNT_AUTH_IDENTITY_W)pAuthData; + (PSEC_WINNT_AUTH_IDENTITY_W)pAuthData; + + TRACE("Username is %s\n", debugstr_wn(auth_data->User, auth_data->UserLength)); + TRACE("Domain name is %s\n", debugstr_wn(auth_data->Domain, auth_data->DomainLength)); + + ntlm_cred->username_arg = ntlm_GetUsernameArg(auth_data->User, auth_data->UserLength); + ntlm_cred->domain_arg = ntlm_GetDomainArg(auth_data->Domain, auth_data->DomainLength); if(auth_data->PasswordLength != 0) { @@ -400,6 +380,46 @@ static int ntlm_GetDataBufferIndex(PSecBufferDesc pMessage) return -1; } +static BOOL ntlm_GetCachedCredential(const SEC_WCHAR *pszTargetName, PCREDENTIALW *cred) +{ + LPCWSTR p; + LPCWSTR pszHost; + LPWSTR pszHostOnly; + BOOL ret; + + if (!pszTargetName) + return FALSE; + + /* try to get the start of the hostname from service principal name (SPN) */ + pszHost = strchrW(pszTargetName, '/'); + if (pszHost) + { + /* skip slash character */ + pszHost++; + + /* find end of host by detecting start of instance port or start of referrer */ + p = strchrW(pszHost, ':'); + if (!p) + p = strchrW(pszHost, '/'); + if (!p) + p = pszHost + strlenW(pszHost); + } + else /* otherwise not an SPN, just a host */ + p = pszHost + strlenW(pszHost); + + pszHostOnly = HeapAlloc(GetProcessHeap(), 0, (p - pszHost + 1) * sizeof(WCHAR)); + if (!pszHostOnly) + return FALSE; + + memcpy(pszHostOnly, pszHost, (p - pszHost) * sizeof(WCHAR)); + pszHostOnly[p - pszHost] = '\0'; + + ret = CredReadW(pszHostOnly, CRED_TYPE_DOMAIN_PASSWORD, 0, cred); + + HeapFree(GetProcessHeap(), 0, pszHostOnly); + return ret; +} + /*********************************************************************** * InitializeSecurityContextW */ @@ -417,6 +437,9 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW( PBYTE bin; int buffer_len, bin_len, max_len = NTLM_MAX_BUF; int token_idx; + SEC_CHAR *username = NULL; + SEC_CHAR *domain = NULL; + SEC_CHAR *password = NULL; TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext, debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput, @@ -436,11 +459,6 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW( */ /* The squid cache size is 2010 chars, and that's what ntlm_auth uses */ - if (pszTargetName) - { - TRACE("According to a MS whitepaper pszTargetName is ignored.\n"); - } - if(TargetDataRep == SECURITY_NETWORK_DREP){ TRACE("Setting SECURITY_NETWORK_DREP\n"); } @@ -452,7 +470,8 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW( { static char helper_protocol[] = "--helper-protocol=ntlmssp-client-1"; static CHAR credentials_argv[] = "--use-cached-creds"; - SEC_CHAR *client_argv[6]; + SEC_CHAR *client_argv[5]; + int pwlen = 0; TRACE("First time in ISC()\n"); @@ -475,10 +494,73 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW( client_argv[0] = ntlm_auth; client_argv[1] = helper_protocol; - client_argv[2] = ntlm_cred->username_arg; - client_argv[3] = ntlm_cred->domain_arg; - client_argv[4] = credentials_argv; - client_argv[5] = NULL; + if (!ntlm_cred->username_arg && !ntlm_cred->domain_arg) + { + LPWKSTA_USER_INFO_1 ui = NULL; + NET_API_STATUS status; + PCREDENTIALW cred; + + if (ntlm_GetCachedCredential(pszTargetName, &cred)) + { + LPWSTR p; + p = strchrW(cred->UserName, '\\'); + if (p) + { + domain = ntlm_GetDomainArg(cred->UserName, p - cred->UserName); + p++; + } + else + { + domain = ntlm_GetDomainArg(NULL, 0); + p = cred->UserName; + } + + username = ntlm_GetUsernameArg(p, -1); + + if(cred->CredentialBlobSize != 0) + { + pwlen = WideCharToMultiByte(CP_UNIXCP, + WC_NO_BEST_FIT_CHARS, (LPWSTR)cred->CredentialBlob, + cred->CredentialBlobSize / sizeof(WCHAR), NULL, 0, + NULL, NULL); + + password = HeapAlloc(GetProcessHeap(), 0, pwlen); + + WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, + (LPWSTR)cred->CredentialBlob, + cred->CredentialBlobSize / sizeof(WCHAR), + password, pwlen, NULL, NULL); + } + + CredFree(cred); + + client_argv[2] = username; + client_argv[3] = domain; + client_argv[4] = NULL; + } + else + { + status = NetWkstaUserGetInfo(NULL, 1, (LPBYTE *)&ui); + if (status != NERR_Success || ui == NULL) + { + ret = SEC_E_NO_CREDENTIALS; + goto isc_end; + } + username = ntlm_GetUsernameArg(ui->wkui1_username, -1); + + TRACE("using cached credentials\n"); + + client_argv[2] = username; + client_argv[3] = credentials_argv; + client_argv[4] = NULL; + } + } + else + { + client_argv[2] = ntlm_cred->username_arg; + client_argv[3] = ntlm_cred->domain_arg; + client_argv[4] = NULL; + } if((ret = fork_helper(&helper, ntlm_auth, client_argv)) != SEC_E_OK) goto isc_end; @@ -493,19 +575,20 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW( } /* Generate the dummy session key = MD4(MD4(password))*/ - if(ntlm_cred->password) + if(password || ntlm_cred->password) { SEC_WCHAR *unicode_password; int passwd_lenW; TRACE("Converting password to unicode.\n"); passwd_lenW = MultiByteToWideChar(CP_ACP, 0, - (LPCSTR)ntlm_cred->password, ntlm_cred->pwlen, + password ? (LPCSTR)password : (LPCSTR)ntlm_cred->password, + password ? pwlen : ntlm_cred->pwlen, NULL, 0); unicode_password = HeapAlloc(GetProcessHeap(), 0, passwd_lenW * sizeof(SEC_WCHAR)); - MultiByteToWideChar(CP_ACP, 0, (LPCSTR)ntlm_cred->password, - ntlm_cred->pwlen, unicode_password, passwd_lenW); + MultiByteToWideChar(CP_ACP, 0, password ? (LPCSTR)password : (LPCSTR)ntlm_cred->password, + password ? pwlen : ntlm_cred->pwlen, unicode_password, passwd_lenW); SECUR32_CreateNTLMv1SessionKey((PBYTE)unicode_password, passwd_lenW * sizeof(SEC_WCHAR), helper->session_key); @@ -566,7 +649,7 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW( /* If no password is given, try to use cached credentials. Fall back to an empty * password if this failed. */ - if(ntlm_cred->password == NULL) + if(!password && !ntlm_cred->password) { lstrcpynA(buffer, "OK", max_len-1); if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK) @@ -577,8 +660,9 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW( /* If the helper replied with "PW", using cached credentials failed */ if(!strncmp(buffer, "PW", 2)) { - TRACE("Using cached credentials failed. Using empty password.\n"); - lstrcpynA(buffer, "PW AA==", max_len-1); + TRACE("Using cached credentials failed.\n"); + ret = SEC_E_NO_CREDENTIALS; + goto isc_end; } else /* Just do a noop on the next run */ lstrcpynA(buffer, "OK", max_len-1); @@ -586,8 +670,8 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW( else { lstrcpynA(buffer, "PW ", max_len-1); - if((ret = encodeBase64((unsigned char*)ntlm_cred->password, - ntlm_cred->pwlen, buffer+3, + if((ret = encodeBase64(password ? (unsigned char *)password : (unsigned char *)ntlm_cred->password, + password ? pwlen : ntlm_cred->pwlen, buffer+3, max_len-3, &buffer_len)) != SEC_E_OK) { cleanup_helper(helper); @@ -840,6 +924,9 @@ static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW( } isc_end: + HeapFree(GetProcessHeap(), 0, username); + HeapFree(GetProcessHeap(), 0, domain); + HeapFree(GetProcessHeap(), 0, password); HeapFree(GetProcessHeap(), 0, want_flags); HeapFree(GetProcessHeap(), 0, buffer); HeapFree(GetProcessHeap(), 0, bin); diff --git a/dlls/shell32/shell32_main.c b/dlls/shell32/shell32_main.c index 37694ba6c4e..a64381f8a47 100644 --- a/dlls/shell32/shell32_main.c +++ b/dlls/shell32/shell32_main.c @@ -97,20 +97,20 @@ LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs) /* Return the path to the executable */ DWORD len, size=16; - hargv=GlobalAlloc(0, size); - argv=GlobalLock(hargv); + hargv=LocalAlloc(0, size); + argv=LocalLock(hargv); for (;;) { len = GetModuleFileNameW(0, (LPWSTR)(argv+1), (size-sizeof(LPWSTR))/sizeof(WCHAR)); if (!len) { - GlobalFree(hargv); + LocalFree(hargv); return NULL; } if (len < size) break; size*=2; - hargv=GlobalReAlloc(hargv, size, 0); - argv=GlobalLock(hargv); + hargv=LocalReAlloc(hargv, size, 0); + argv=LocalLock(hargv); } argv[0]=(LPWSTR)(argv+1); if (numargs) diff --git a/dlls/shell32/shfldr_unixfs.c b/dlls/shell32/shfldr_unixfs.c index ab1f78a6aa6..5f30cd9f3a7 100644 --- a/dlls/shell32/shfldr_unixfs.c +++ b/dlls/shell32/shfldr_unixfs.c @@ -1761,7 +1761,7 @@ static HRESULT WINAPI UnixFolder_ISFHelper_AddFolder(ISFHelper* iface, HWND hwnd cBaseLen = lstrlenA(szNewDir); WideCharToMultiByte(CP_UNIXCP, 0, pwszName, -1, szNewDir+cBaseLen, FILENAME_MAX-cBaseLen, 0, 0); - if (mkdir(szNewDir, 0755)) { + if (mkdir(szNewDir, 0777)) { char szMessage[256 + FILENAME_MAX]; char szCaption[256]; diff --git a/dlls/shell32/systray.c b/dlls/shell32/systray.c index cb67fd8af88..7743ce9e24b 100644 --- a/dlls/shell32/systray.c +++ b/dlls/shell32/systray.c @@ -104,6 +104,7 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid) HWND tray; COPYDATASTRUCT cds; char *buffer = NULL; + BOOL ret; TRACE("dwMessage = %d, nid->cbSize=%d\n", dwMessage, nid->cbSize); @@ -185,11 +186,11 @@ noicon: cds.lpData = nid; } - SendMessageW(tray, WM_COPYDATA, (WPARAM)nid->hWnd, (LPARAM)&cds); + ret = SendMessageW(tray, WM_COPYDATA, (WPARAM)nid->hWnd, (LPARAM)&cds); /* FIXME: if statement only needed because we don't support interprocess * icon handles */ HeapFree(GetProcessHeap(), 0, buffer); - return TRUE; + return ret; } diff --git a/dlls/shell32/tests/shelllink.c b/dlls/shell32/tests/shelllink.c index 7983aa0c961..e94dc7df719 100644 --- a/dlls/shell32/tests/shelllink.c +++ b/dlls/shell32/tests/shelllink.c @@ -146,7 +146,7 @@ static void test_get_set(void) ok(SUCCEEDED(r), "GetWorkingDirectory failed (0x%08x)\n", r); ok(lstrcmpi(buffer,str)==0, "GetWorkingDirectory returned '%s'\n", buffer); - /* Test Getting / Setting the work directory */ + /* Test Getting / Setting the path */ strcpy(buffer,"garbage"); r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); ok(SUCCEEDED(r), "GetPath failed (0x%08x)\n", r); @@ -283,7 +283,7 @@ static void test_get_set(void) i=0xdeadbeef; r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); ok(SUCCEEDED(r), "GetIconLocation failed (0x%08x)\n", r); - ok(lstrcmpi(buffer,str)==0, "GetArguments returned '%s'\n", buffer); + ok(lstrcmpi(buffer,str)==0, "GetIconLocation returned '%s'\n", buffer); ok(i==0xbabecafe, "GetIconLocation returned %d'\n", i); /* Test Getting / Setting the hot key */ diff --git a/dlls/shell32/tests/shellpath.c b/dlls/shell32/tests/shellpath.c index 6fb485e178f..ff041c82963 100644 --- a/dlls/shell32/tests/shellpath.c +++ b/dlls/shell32/tests/shellpath.c @@ -864,8 +864,7 @@ static void testNonExistentPath(void) startup.dwFlags = SW_SHOWNORMAL; CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info); - ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, - "child process termination\n"); + winetest_wait_child_process( info.hProcess ); /* Query the path to be able to delete it below */ hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES, NULL, diff --git a/dlls/shell32/tests/systray.c b/dlls/shell32/tests/systray.c index 35a59ad6d82..23e1ba3fc5e 100644 --- a/dlls/shell32/tests/systray.c +++ b/dlls/shell32/tests/systray.c @@ -52,8 +52,7 @@ void test_cbsize(void) ok(pShell_NotifyIconW(NIM_DELETE, &nidW), "NIM_DELETE failed!\n"); /* as icon doesn't exist anymore - now there will be an error */ nidW.cbSize = sizeof(nidW); - /* wine currently doesn't return error code put prints an ERR(...) */ - todo_wine ok(!pShell_NotifyIconW(NIM_DELETE, &nidW), "The icon was not deleted\n"); + ok(!pShell_NotifyIconW(NIM_DELETE, &nidW), "The icon was not deleted\n"); } /* same for Shell_NotifyIconA */ @@ -73,8 +72,7 @@ void test_cbsize(void) ok(Shell_NotifyIconA(NIM_DELETE, &nidA), "NIM_DELETE failed!\n"); /* as icon doesn't exist anymore - now there will be an error */ nidA.cbSize = sizeof(nidA); - /* wine currently doesn't return error code put prints an ERR(...) */ - todo_wine ok(!Shell_NotifyIconA(NIM_DELETE, &nidA), "The icon was not deleted\n"); + ok(!Shell_NotifyIconA(NIM_DELETE, &nidA), "The icon was not deleted\n"); } START_TEST(systray) diff --git a/dlls/url/url.spec b/dlls/url/url.spec index 4577a6dd295..cedd9e4d545 100644 --- a/dlls/url/url.spec +++ b/dlls/url/url.spec @@ -1,4 +1,4 @@ -@ stub AddMIMEFileTypesPS +@ stdcall AddMIMEFileTypesPS(ptr ptr) @ stub AutodialHookCallback @ stub DllCanUnloadNow @ stub DllGetClassObject diff --git a/dlls/url/url_main.c b/dlls/url/url_main.c index d7e1711fbc0..69b46eaa317 100644 --- a/dlls/url/url_main.c +++ b/dlls/url/url_main.c @@ -24,6 +24,9 @@ #include "shellapi.h" #include "shlwapi.h" #include "intshcut.h" +#include "winuser.h" +#include "commctrl.h" +#include "prsht.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(url); @@ -45,6 +48,25 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) } /*********************************************************************** + * AddMIMEFileTypesPS (URL.@) + * + * Build and Manage a Filetype-Association Property Sheet + * + * PARAMS + * unknown1 [I] Pointer to an Read-Only Area + * lppsh [I] PTR to the target PropertySheetHeader (ANSI) + * + * RETURNS + * Success: 0 + * + */ +DWORD WINAPI AddMIMEFileTypesPS(VOID * unknown1, LPPROPSHEETHEADERA lppsh) +{ + FIXME("(%p, %p): stub!\n", unknown1, lppsh); + return 0; +} + +/*********************************************************************** * InetIsOffline (URL.@) * */ diff --git a/dlls/urlmon/binding.c b/dlls/urlmon/binding.c index 66b5bdfd66b..b5646515761 100644 --- a/dlls/urlmon/binding.c +++ b/dlls/urlmon/binding.c @@ -38,17 +38,33 @@ typedef struct _task_header_t { } task_header_t; typedef struct { - const IStreamVtbl *lpStreamVtbl; + const IUnknownVtbl *lpUnknownVtbl; LONG ref; IInternetProtocol *protocol; BYTE buf[1024*8]; - DWORD buf_size; - BOOL init_buf; + DWORD size; + BOOL init; HRESULT hres; -} ProtocolStream; + + LPWSTR cache_file; +} stgmed_buf_t; + +typedef struct _stgmed_obj_t stgmed_obj_t; + +typedef struct { + void (*release)(stgmed_obj_t*); + HRESULT (*fill_stgmed)(stgmed_obj_t*,STGMEDIUM*); + void *(*get_result)(stgmed_obj_t*); +} stgmed_obj_vtbl; + +struct _stgmed_obj_t { + const stgmed_obj_vtbl *vtbl; +}; + +#define STGMEDUNK(x) ((IUnknown*) &(x)->lpUnknownVtbl) typedef enum { BEFORE_DOWNLOAD, @@ -71,7 +87,9 @@ struct Binding { IBindStatusCallback *callback; IInternetProtocol *protocol; IServiceProvider *service_provider; - ProtocolStream *stream; + + stgmed_buf_t *stgmed_buf; + stgmed_obj_t *stgmed_obj; BINDINFO bindinfo; DWORD bindf; @@ -92,8 +110,6 @@ struct Binding { DWORD apartment_thread; HWND notif_hwnd; - STGMEDIUM stgmed; - task_header_t *task_queue_head, *task_queue_tail; CRITICAL_SECTION section; }; @@ -143,18 +159,18 @@ static task_header_t *pop_task(Binding *binding) return ret; } -static void fill_stream_buffer(ProtocolStream *This) +static void fill_stgmed_buffer(stgmed_buf_t *buf) { DWORD read = 0; - if(sizeof(This->buf) == This->buf_size) + if(sizeof(buf->buf) == buf->size) return; - This->hres = IInternetProtocol_Read(This->protocol, This->buf+This->buf_size, - sizeof(This->buf)-This->buf_size, &read); - This->buf_size += read; + buf->hres = IInternetProtocol_Read(buf->protocol, buf->buf+buf->size, + sizeof(buf->buf)-buf->size, &read); + buf->size += read; if(read > 0) - This->init_buf = TRUE; + buf->init = TRUE; } static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -281,9 +297,9 @@ static void handle_mime_available(Binding *binding, BOOL verify) if(verify) { LPWSTR mime = NULL; - fill_stream_buffer(binding->stream); - FindMimeFromData(NULL, binding->url, binding->stream->buf, - min(binding->stream->buf_size, 255), binding->mime, 0, &mime, 0); + fill_stgmed_buffer(binding->stgmed_buf); + FindMimeFromData(NULL, binding->url, binding->stgmed_buf->buf, + min(binding->stgmed_buf->size, 255), binding->mime, 0, &mime, 0); heap_free(binding->mime); binding->mime = heap_strdupW(mime); @@ -460,6 +476,90 @@ static void create_object(Binding *binding) stop_binding(binding, S_OK, NULL); } +#define STGMEDUNK_THIS(iface) DEFINE_THIS(stgmed_buf_t, Unknown, iface) + +static HRESULT WINAPI StgMedUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + stgmed_buf_t *This = STGMEDUNK_THIS(iface); + + *ppv = NULL; + + if(IsEqualGUID(riid, &IID_IUnknown)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + + *ppv = STGMEDUNK(This); + IUnknown_AddRef(STGMEDUNK(This)); + return S_OK; + } + + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + return E_NOINTERFACE; +} + +static ULONG WINAPI StgMedUnk_AddRef(IUnknown *iface) +{ + stgmed_buf_t *This = STGMEDUNK_THIS(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI StgMedUnk_Release(IUnknown *iface) +{ + stgmed_buf_t *This = STGMEDUNK_THIS(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) { + IInternetProtocol_Release(This->protocol); + heap_free(This->cache_file); + heap_free(This); + + URLMON_UnlockModule(); + } + + return ref; +} + +#undef STGMEDUNK_THIS + +static const IUnknownVtbl StgMedUnkVtbl = { + StgMedUnk_QueryInterface, + StgMedUnk_AddRef, + StgMedUnk_Release +}; + +static stgmed_buf_t *create_stgmed_buf(IInternetProtocol *protocol) +{ + stgmed_buf_t *ret = heap_alloc(sizeof(*ret)); + + ret->lpUnknownVtbl = &StgMedUnkVtbl; + ret->ref = 1; + ret->size = 0; + ret->init = FALSE; + ret->hres = S_OK; + ret->cache_file = NULL; + + IInternetProtocol_AddRef(protocol); + ret->protocol = protocol; + + URLMON_LockModule(); + + return ret; +} + +typedef struct { + stgmed_obj_t stgmed_obj; + const IStreamVtbl *lpStreamVtbl; + + LONG ref; + + stgmed_buf_t *buf; +} ProtocolStream; + #define STREAM_THIS(iface) DEFINE_THIS(ProtocolStream, Stream, iface) static HRESULT WINAPI ProtocolStream_QueryInterface(IStream *iface, @@ -507,7 +607,7 @@ static ULONG WINAPI ProtocolStream_Release(IStream *iface) TRACE("(%p) ref=%d\n", This, ref); if(!ref) { - IInternetProtocol_Release(This->protocol); + IUnknown_Release(STGMEDUNK(This->buf)); heap_free(This); URLMON_UnlockModule(); @@ -517,24 +617,25 @@ static ULONG WINAPI ProtocolStream_Release(IStream *iface) } static HRESULT WINAPI ProtocolStream_Read(IStream *iface, void *pv, - ULONG cb, ULONG *pcbRead) + ULONG cb, ULONG *pcbRead) { ProtocolStream *This = STREAM_THIS(iface); DWORD read = 0, pread = 0; + HRESULT hres; TRACE("(%p)->(%p %d %p)\n", This, pv, cb, pcbRead); - if(This->buf_size) { + if(This->buf->size) { read = cb; - if(read > This->buf_size) - read = This->buf_size; + if(read > This->buf->size) + read = This->buf->size; - memcpy(pv, This->buf, read); + memcpy(pv, This->buf->buf, read); - if(read < This->buf_size) - memmove(This->buf, This->buf+read, This->buf_size-read); - This->buf_size -= read; + if(read < This->buf->size) + memmove(This->buf->buf, This->buf->buf+read, This->buf->size-read); + This->buf->size -= read; } if(read == cb) { @@ -543,14 +644,14 @@ static HRESULT WINAPI ProtocolStream_Read(IStream *iface, void *pv, return S_OK; } - This->hres = IInternetProtocol_Read(This->protocol, (PBYTE)pv+read, cb-read, &pread); + hres = This->buf->hres = IInternetProtocol_Read(This->buf->protocol, (PBYTE)pv+read, cb-read, &pread); if (pcbRead) *pcbRead = read + pread; - if(This->hres == E_PENDING) + if(hres == E_PENDING) return E_PENDING; - else if(FAILED(This->hres)) - FIXME("Read failed: %08x\n", This->hres); + else if(FAILED(hres)) + FIXME("Read failed: %08x\n", hres); return read || pread ? S_OK : S_FALSE; } @@ -656,26 +757,118 @@ static const IStreamVtbl ProtocolStreamVtbl = { ProtocolStream_Clone }; -#define BINDING_THIS(iface) DEFINE_THIS(Binding, Binding, iface) +static void stgmed_stream_release(stgmed_obj_t *obj) +{ + ProtocolStream *stream = (ProtocolStream*)obj; + IStream_Release(STREAM(stream)); +} -static ProtocolStream *create_stream(IInternetProtocol *protocol) +static HRESULT stgmed_stream_fill_stgmed(stgmed_obj_t *obj, STGMEDIUM *stgmed) +{ + ProtocolStream *stream = (ProtocolStream*)obj; + + stgmed->tymed = TYMED_ISTREAM; + stgmed->u.pstm = STREAM(stream); + stgmed->pUnkForRelease = STGMEDUNK(stream->buf); + + return S_OK; +} + +static void *stgmed_stream_get_result(stgmed_obj_t *obj) +{ + ProtocolStream *stream = (ProtocolStream*)obj; + + IStream_AddRef(STREAM(stream)); + return STREAM(stream); +} + +static const stgmed_obj_vtbl stgmed_stream_vtbl = { + stgmed_stream_release, + stgmed_stream_fill_stgmed, + stgmed_stream_get_result +}; + +typedef struct { + stgmed_obj_t stgmed_obj; + stgmed_buf_t *buf; +} stgmed_file_obj_t; + +static stgmed_obj_t *create_stgmed_stream(stgmed_buf_t *buf) { ProtocolStream *ret = heap_alloc(sizeof(ProtocolStream)); + ret->stgmed_obj.vtbl = &stgmed_stream_vtbl; ret->lpStreamVtbl = &ProtocolStreamVtbl; ret->ref = 1; - ret->buf_size = 0; - ret->init_buf = FALSE; - ret->hres = S_OK; - IInternetProtocol_AddRef(protocol); - ret->protocol = protocol; + IUnknown_AddRef(STGMEDUNK(buf)); + ret->buf = buf; URLMON_LockModule(); - return ret; + return &ret->stgmed_obj; +} + +static void stgmed_file_release(stgmed_obj_t *obj) +{ + stgmed_file_obj_t *file_obj = (stgmed_file_obj_t*)obj; + + IUnknown_Release(STGMEDUNK(file_obj->buf)); + heap_free(file_obj); +} + +static HRESULT stgmed_file_fill_stgmed(stgmed_obj_t *obj, STGMEDIUM *stgmed) +{ + stgmed_file_obj_t *file_obj = (stgmed_file_obj_t*)obj; + + if(!file_obj->buf->cache_file) { + WARN("cache_file not set\n"); + return INET_E_DATA_NOT_AVAILABLE; + } + + fill_stgmed_buffer(file_obj->buf); + if(file_obj->buf->size == sizeof(file_obj->buf->buf)) { + BYTE buf[1024]; + DWORD read; + HRESULT hres; + + do { + hres = IInternetProtocol_Read(file_obj->buf->protocol, buf, sizeof(buf), &read); + }while(hres == S_OK); + } + + stgmed->tymed = TYMED_FILE; + stgmed->u.lpszFileName = file_obj->buf->cache_file; + stgmed->pUnkForRelease = STGMEDUNK(file_obj->buf); + + return S_OK; +} + +static void *stgmed_file_get_result(stgmed_obj_t *obj) +{ + return NULL; } +static const stgmed_obj_vtbl stgmed_file_vtbl = { + stgmed_file_release, + stgmed_file_fill_stgmed, + stgmed_file_get_result +}; + +static stgmed_obj_t *create_stgmed_file(stgmed_buf_t *buf) +{ + stgmed_file_obj_t *ret = heap_alloc(sizeof(*ret)); + + ret->stgmed_obj.vtbl = &stgmed_file_vtbl; + + IUnknown_AddRef(STGMEDUNK(buf)); + ret->buf = buf; + + return &ret->stgmed_obj; +} + +#define BINDING_THIS(iface) DEFINE_THIS(Binding, Binding, iface) + static HRESULT WINAPI Binding_QueryInterface(IBinding *iface, REFIID riid, void **ppv) { Binding *This = BINDING_THIS(iface); @@ -736,8 +929,10 @@ static ULONG WINAPI Binding_Release(IBinding *iface) IInternetProtocol_Release(This->protocol); if(This->service_provider) IServiceProvider_Release(This->service_provider); - if(This->stream) - IStream_Release(STREAM(This->stream)); + if(This->stgmed_buf) + IUnknown_Release(STGMEDUNK(This->stgmed_buf)); + if(This->stgmed_obj) + This->stgmed_obj->vtbl->release(This->stgmed_obj); if(This->obj) IUnknown_Release(This->obj); if(This->bctx) @@ -957,7 +1152,7 @@ static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink on_progress(This, 0, 0, BINDSTATUS_CONNECTING, szStatusText); break; case BINDSTATUS_BEGINDOWNLOADDATA: - fill_stream_buffer(This->stream); + fill_stgmed_buffer(This->stgmed_buf); break; case BINDSTATUS_MIMETYPEAVAILABLE: set_binding_mime(This, szStatusText); @@ -971,6 +1166,8 @@ static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink mime_available(This, szStatusText, FALSE); break; case BINDSTATUS_CACHEFILENAMEAVAILABLE: + heap_free(This->stgmed_buf->cache_file); + This->stgmed_buf->cache_file = heap_strdupW(szStatusText); break; case BINDSTATUS_DIRECTBIND: This->report_mime = FALSE; @@ -1000,15 +1197,19 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres mime_available(This, NULL, TRUE); if(This->download_state == BEFORE_DOWNLOAD) { - fill_stream_buffer(This->stream); + fill_stgmed_buffer(This->stgmed_buf); This->download_state = DOWNLOADING; sent_begindownloaddata = TRUE; IBindStatusCallback_OnProgress(This->callback, progress, progress_max, BINDSTATUS_BEGINDOWNLOADDATA, This->url); + + if(This->stgmed_buf->cache_file) + IBindStatusCallback_OnProgress(This->callback, progress, progress_max, + BINDSTATUS_CACHEFILENAMEAVAILABLE, This->stgmed_buf->cache_file); } - if(This->stream->hres == S_FALSE || (bscf & BSCF_LASTDATANOTIFICATION)) { + if(This->stgmed_buf->hres == S_FALSE || (bscf & BSCF_LASTDATANOTIFICATION)) { This->download_state = END_DOWNLOAD; IBindStatusCallback_OnProgress(This->callback, progress, progress_max, BINDSTATUS_ENDDOWNLOADDATA, This->url); @@ -1021,15 +1222,26 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres if(!(This->state & BINDING_OBJAVAIL)) create_object(This); }else { + STGMEDIUM stgmed; + HRESULT hres; + if(!(This->state & BINDING_LOCKED)) { HRESULT hres = IInternetProtocol_LockRequest(This->protocol, 0); if(SUCCEEDED(hres)) This->state |= BINDING_LOCKED; } + hres = This->stgmed_obj->vtbl->fill_stgmed(This->stgmed_obj, &stgmed); + if(FAILED(hres)) { + stop_binding(This, hres, NULL); + return; + } + + formatetc.tymed = stgmed.tymed; formatetc.cfFormat = This->clipboard_format; + IBindStatusCallback_OnDataAvailable(This->callback, bscf, progress, - &formatetc, &This->stgmed); + &formatetc, &stgmed); if(This->download_state == END_DOWNLOAD) stop_binding(This, S_OK, NULL); @@ -1283,7 +1495,7 @@ static HRESULT get_callback(IBindCtx *pbc, IBindStatusCallback **callback) IUnknown_Release(unk); } - return SUCCEEDED(hres) ? S_OK : MK_E_SYNTAX; + return SUCCEEDED(hres) ? S_OK : INET_E_DATA_NOT_AVAILABLE; } static BOOL is_urlmon_protocol(LPCWSTR url) @@ -1326,11 +1538,6 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, Binding *ret; HRESULT hres; - if(!to_obj && !IsEqualGUID(&IID_IStream, riid)) { - FIXME("Unsupported riid %s\n", debugstr_guid(riid)); - return E_NOTIMPL; - } - URLMON_LockModule(); ret = heap_alloc_zero(sizeof(Binding)); @@ -1406,15 +1613,25 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, ret->url = heap_strdupW(url); if(binding_ctx) { - ret->stream = binding_ctx->stream; - IStream_AddRef(STREAM(ret->stream)); + ret->stgmed_buf = binding_ctx->stgmed_buf; + IUnknown_AddRef(STGMEDUNK(ret->stgmed_buf)); ret->clipboard_format = binding_ctx->clipboard_format; }else { - ret->stream = create_stream(ret->protocol); + ret->stgmed_buf = create_stgmed_buf(ret->protocol); + } + + if(to_obj) { + ret->stgmed_obj = NULL; + }else if(IsEqualGUID(&IID_IStream, riid)) { + ret->stgmed_obj = create_stgmed_stream(ret->stgmed_buf); + }else if(IsEqualGUID(&IID_IUnknown, riid)) { + ret->bindf |= BINDF_NEEDFILE; + ret->stgmed_obj = create_stgmed_file(ret->stgmed_buf); + }else { + FIXME("Unsupported riid %s\n", debugstr_guid(riid)); + IBinding_Release(BINDING(ret)); + return E_NOTIMPL; } - ret->stgmed.tymed = TYMED_ISTREAM; - ret->stgmed.u.pstm = STREAM(ret->stream); - ret->stgmed.pUnkForRelease = (IUnknown*)BINDING(ret); /* NOTE: Windows uses other IUnknown */ *binding = ret; return S_OK; @@ -1484,23 +1701,16 @@ HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv) if(FAILED(hres)) return hres; - if(binding->hres != S_OK) { - hres = SUCCEEDED(binding->hres) ? S_OK : binding->hres; - }else if(binding->stream->init_buf) { + if(binding->hres == S_OK && binding->stgmed_buf->init) { if((binding->state & BINDING_STOPPED) && (binding->state & BINDING_LOCKED)) IInternetProtocol_UnlockRequest(binding->protocol); - IStream_AddRef(STREAM(binding->stream)); - *ppv = binding->stream; - - hres = S_OK; - }else { - hres = MK_S_ASYNCHRONOUS; + *ppv = binding->stgmed_obj->vtbl->get_result(binding->stgmed_obj); } IBinding_Release(BINDING(binding)); - return hres; + return *ppv ? S_OK : MK_S_ASYNCHRONOUS; } HRESULT bind_to_object(IMoniker *mon, LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv) diff --git a/dlls/urlmon/http.c b/dlls/urlmon/http.c index 3056febf3e0..712800df4b2 100644 --- a/dlls/urlmon/http.c +++ b/dlls/urlmon/http.c @@ -419,6 +419,8 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl if (This->grfBINDF & BINDF_NOWRITECACHE) request_flags |= INTERNET_FLAG_NO_CACHE_WRITE; + if (This->grfBINDF & BINDF_NEEDFILE) + request_flags |= INTERNET_FLAG_NEED_FILE; This->request = HttpOpenRequestW(This->connect, This->bind_info.dwBindVerb < BINDVERB_CUSTOM ? wszBindVerb[This->bind_info.dwBindVerb] : This->bind_info.szCustomVerb, @@ -656,6 +658,21 @@ static HRESULT WINAPI HttpProtocol_Continue(IInternetProtocol *iface, PROTOCOLDA This->content_length = atoiW(content_length); } + if(This->grfBINDF & BINDF_NEEDFILE) { + WCHAR cache_file[MAX_PATH]; + DWORD buflen = sizeof(cache_file); + + if(InternetQueryOptionW(This->request, INTERNET_OPTION_DATAFILE_NAME, + cache_file, &buflen)) + { + IInternetProtocolSink_ReportProgress(This->protocol_sink, + BINDSTATUS_CACHEFILENAMEAVAILABLE, + cache_file); + }else { + FIXME("Could not get cache file\n"); + } + } + This->flags |= FLAG_FIRST_CONTINUE_COMPLETE; } diff --git a/dlls/urlmon/session.c b/dlls/urlmon/session.c index 3571b050384..9ce7b662bd9 100644 --- a/dlls/urlmon/session.c +++ b/dlls/urlmon/session.c @@ -95,9 +95,26 @@ static HRESULT get_protocol_cf(LPCWSTR schema, DWORD schema_len, CLSID *pclsid, if(pclsid) *pclsid = clsid; + if(!ret) + return S_OK; + return CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)ret); } +BOOL is_registered_protocol(LPCWSTR url) +{ + DWORD schema_len; + WCHAR schema[64]; + HRESULT hres; + + hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(schema[0]), + &schema_len, 0); + if(FAILED(hres)) + return FALSE; + + return get_protocol_cf(schema, schema_len, NULL, NULL) == S_OK; +} + IInternetProtocolInfo *get_protocol_info(LPCWSTR url) { IInternetProtocolInfo *ret = NULL; diff --git a/dlls/urlmon/tests/Makefile.in b/dlls/urlmon/tests/Makefile.in index 808e3a49b05..9cdff83484a 100644 --- a/dlls/urlmon/tests/Makefile.in +++ b/dlls/urlmon/tests/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../../.. SRCDIR = @srcdir@ VPATH = @srcdir@ TESTDLL = urlmon.dll -IMPORTS = urlmon user32 kernel32 ole32 +IMPORTS = urlmon ole32 user32 advapi32 kernel32 EXTRALIBS = -luuid CTESTS = \ diff --git a/dlls/urlmon/tests/misc.c b/dlls/urlmon/tests/misc.c index ba36d8ac300..1ed76146ae0 100644 --- a/dlls/urlmon/tests/misc.c +++ b/dlls/urlmon/tests/misc.c @@ -18,6 +18,7 @@ #define COBJMACROS #define CONST_VTABLE +#define NONAMELESSUNION #include #include @@ -258,6 +259,9 @@ 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 url4e[] = {'f','i','l','e',':','s','o','m','e',' ','f','i','l','e', @@ -1174,6 +1178,37 @@ static void test_ReleaseBindInfo(void) ok(bi.pUnk == &unk, "bi.pUnk=%p, expected %p\n", bi.pUnk, &unk); } +static void test_CopyStgMedium(void) +{ + STGMEDIUM src, dst; + HRESULT hres; + + memset(&src, 0xf0, sizeof(src)); + memset(&dst, 0xe0, sizeof(dst)); + src.tymed = TYMED_NULL; + src.pUnkForRelease = NULL; + hres = CopyStgMedium(&src, &dst); + ok(hres == S_OK, "CopyStgMedium failed: %08x\n", hres); + ok(dst.tymed == TYMED_NULL, "tymed=%d\n", dst.tymed); + ok(dst.u.hGlobal == (void*)0xf0f0f0f0, "u=%p\n", dst.u.hGlobal); + ok(!dst.pUnkForRelease, "pUnkForRelease=%p, expected NULL\n", dst.pUnkForRelease); + + memset(&dst, 0xe0, sizeof(dst)); + src.tymed = TYMED_ISTREAM; + src.u.pstm = NULL; + src.pUnkForRelease = NULL; + hres = CopyStgMedium(&src, &dst); + ok(hres == S_OK, "CopyStgMedium failed: %08x\n", hres); + ok(dst.tymed == TYMED_ISTREAM, "tymed=%d\n", dst.tymed); + ok(!dst.u.pstm, "pstm=%p\n", dst.u.pstm); + ok(!dst.pUnkForRelease, "pUnkForRelease=%p, expected NULL\n", dst.pUnkForRelease); + + hres = CopyStgMedium(&src, NULL); + ok(hres == E_POINTER, "CopyStgMedium failed: %08x, expected E_POINTER\n", hres); + hres = CopyStgMedium(NULL, &dst); + ok(hres == E_POINTER, "CopyStgMedium failed: %08x, expected E_POINTER\n", hres); +} + static void test_UrlMkGetSessionOption(void) { DWORD encoding, size; @@ -1271,6 +1306,54 @@ static void test_ObtainUserAgentString(void) HeapFree(GetProcessHeap(), 0, str2); } +static void test_MkParseDisplayNameEx(void) +{ + IMoniker *mon = NULL; + LPWSTR name; + DWORD issys; + ULONG eaten = 0; + IBindCtx *bctx; + HRESULT hres; + + static const WCHAR clsid_nameW[] = {'c','l','s','i','d',':', + '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8', + '-','0','8','0','0','2','B','3','0','3','0','9','D',':',0}; + + CreateBindCtx(0, &bctx); + + hres = MkParseDisplayNameEx(bctx, url9, &eaten, &mon); + ok(hres == S_OK, "MkParseDisplayNameEx failed: %08x\n", hres); + ok(eaten == sizeof(url9)/sizeof(WCHAR)-1, "eaten=%d\n", eaten); + ok(mon != NULL, "mon == NULL\n"); + + hres = IMoniker_GetDisplayName(mon, NULL, 0, &name); + ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres); + ok(!lstrcmpW(name, url9), "wrong display name %s\n", debugstr_w(name)); + CoTaskMemFree(name); + + hres = IMoniker_IsSystemMoniker(mon, &issys); + ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres); + ok(issys == MKSYS_URLMONIKER, "issys=%x\n", issys); + + IMoniker_Release(mon); + + hres = MkParseDisplayNameEx(bctx, clsid_nameW, &eaten, &mon); + ok(hres == S_OK, "MkParseDisplayNameEx failed: %08x\n", hres); + ok(eaten == sizeof(clsid_nameW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten); + ok(mon != NULL, "mon == NULL\n"); + + hres = IMoniker_IsSystemMoniker(mon, &issys); + ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres); + ok(issys == MKSYS_CLASSMONIKER, "issys=%x\n", issys); + + IMoniker_Release(mon); + + hres = MkParseDisplayNameEx(bctx, url8, &eaten, &mon); + ok(FAILED(hres), "MkParseDisplayNameEx succeeded: %08x\n", hres); + + IBindCtx_Release(bctx); +} + START_TEST(misc) { OleInitialize(NULL); @@ -1288,8 +1371,10 @@ START_TEST(misc) test_NameSpace(); test_MimeFilter(); test_ReleaseBindInfo(); + test_CopyStgMedium(); test_UrlMkGetSessionOption(); test_ObtainUserAgentString(); + test_MkParseDisplayNameEx(); OleUninitialize(); } diff --git a/dlls/urlmon/tests/protocol.c b/dlls/urlmon/tests/protocol.c index fd92171e10d..e9b1ec1e21c 100644 --- a/dlls/urlmon/tests/protocol.c +++ b/dlls/urlmon/tests/protocol.c @@ -36,17 +36,16 @@ #define SET_EXPECT(func) \ expect_ ## func = TRUE -#define CHECK_EXPECT(func) \ +#define CHECK_EXPECT2(func) \ do { \ - ok(expect_ ##func, "unexpected call " #func "\n"); \ - expect_ ## func = FALSE; \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ called_ ## func = TRUE; \ }while(0) -#define CHECK_EXPECT2(func) \ +#define CHECK_EXPECT(func) \ do { \ - ok(expect_ ##func, "unexpected call " #func "\n"); \ - called_ ## func = TRUE; \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ }while(0) #define CHECK_CALLED(func) \ @@ -357,6 +356,8 @@ static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOL CHECK_CALLED(ReportProgress_SENDINGREQUEST); SET_EXPECT(OnResponse); SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE); + if(bindf & BINDF_NEEDFILE) + SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE); } SET_EXPECT(ReportData); @@ -368,6 +369,8 @@ static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOL state = 1; CHECK_CALLED(OnResponse); CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE); + if(bindf & BINDF_NEEDFILE) + CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE); } SetEvent(event_complete); @@ -423,8 +426,10 @@ static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, if(szStatusText) { if(binding_test) ok(szStatusText == expect_wsz, "unexpected szStatusText\n"); + else if(tested_protocol == FILE_TEST) + ok(!lstrcmpW(szStatusText, file_name), "szStatusText = \"%s\"\n", debugstr_w(szStatusText)); else - ok(!lstrcmpW(szStatusText, file_name), "szStatusText != file_name\n"); + ok(szStatusText != NULL, "szStatusText == NULL\n"); } break; case BINDSTATUS_FINDINGRESOURCE: @@ -1408,6 +1413,8 @@ static void test_file_protocol(void) { test_file_protocol_url(index_url); bindf = BINDF_FROMURLMON; test_file_protocol_url(index_url); + bindf = BINDF_FROMURLMON | BINDF_NEEDFILE; + test_file_protocol_url(index_url); memcpy(buf, wszFile, sizeof(wszFile)); len = sizeof(wszFile)/sizeof(WCHAR)-1; @@ -1639,11 +1646,15 @@ static void test_http_protocol(void) bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON; test_http_protocol_url(winehq_url, FALSE); + trace("Testing http protocol (to file)...\n"); + bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE; + test_http_protocol_url(winehq_url, FALSE); + trace("Testing http protocol (post data)...\n"); http_post_test = TRUE; /* Without this flag we get a ReportProgress_CACHEFILENAMEAVAILABLE * notification with BINDVERB_POST */ - bindf |= BINDF_NOWRITECACHE; + bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE; test_http_protocol_url(posttest_url, TRUE); http_post_test = FALSE; } diff --git a/dlls/urlmon/tests/url.c b/dlls/urlmon/tests/url.c index 91366aa5140..dec6da88e33 100644 --- a/dlls/urlmon/tests/url.c +++ b/dlls/urlmon/tests/url.c @@ -23,6 +23,7 @@ #include #define COBJMACROS +#define NONAMELESSUNION #define CONST_VTABLE #include "windef.h" @@ -37,11 +38,12 @@ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE #define SET_EXPECT(func) \ - expect_ ## func = TRUE + do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0) #define CHECK_EXPECT2(func) \ do { \ ok(expect_ ##func, "unexpected call " #func "\n"); \ + if(0) trace("%s\n", #func); \ called_ ## func = TRUE; \ }while(0) @@ -89,6 +91,7 @@ DEFINE_EXPECT(OnProgress_MIMETYPEAVAILABLE); DEFINE_EXPECT(OnProgress_BEGINDOWNLOADDATA); DEFINE_EXPECT(OnProgress_DOWNLOADINGDATA); DEFINE_EXPECT(OnProgress_ENDDOWNLOADDATA); +DEFINE_EXPECT(OnProgress_CACHEFILENAMEAVAILABLE); DEFINE_EXPECT(OnStopBinding); DEFINE_EXPECT(OnDataAvailable); DEFINE_EXPECT(OnObjectAvailable); @@ -104,6 +107,7 @@ DEFINE_EXPECT(Obj_OnProgress_BEGINSYNCOPERATION); DEFINE_EXPECT(Obj_OnProgress_ENDSYNCOPERATION); DEFINE_EXPECT(Obj_OnProgress_FINDINGRESOURCE); DEFINE_EXPECT(Obj_OnProgress_CONNECTING); +DEFINE_EXPECT(Obj_OnProgress_CACHEFILENAMEAVAILABLE); DEFINE_EXPECT(Start); DEFINE_EXPECT(Read); DEFINE_EXPECT(LockRequest); @@ -140,11 +144,12 @@ static const WCHAR wszWineHQSite[] = static const WCHAR wszWineHQIP[] = {'2','0','9','.','3','2','.','1','4','1','.','3',0}; static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0}; +static const WCHAR cache_fileW[] = {'c',':','\\','c','a','c','h','e','.','h','t','m',0}; static const WCHAR emptyW[] = {0}; static BOOL stopped_binding = FALSE, stopped_obj_binding = FALSE, emulate_protocol = FALSE, data_available = FALSE, http_is_first = TRUE, bind_to_object = FALSE; -static DWORD read = 0, bindf = 0, prot_state = 0, thread_id; +static DWORD read = 0, bindf = 0, prot_state = 0, thread_id, tymed; static CHAR mime_type[512]; static IInternetProtocolSink *protocol_sink = NULL; static HANDLE complete_event, complete_event2; @@ -337,8 +342,9 @@ static DWORD WINAPI thread_proc(PVOID arg) CHECK_CALLED(OnDataAvailable); CHECK_CALLED(OnStopBinding); - SetEvent(complete_event2); + SET_EXPECT(Read); + SetEvent(complete_event2); return 0; } @@ -379,7 +385,8 @@ static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo); ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres); - if(test_protocol == FILE_TEST || test_protocol == MK_TEST || test_protocol == HTTP_TEST) { + if(tymed == TYMED_ISTREAM + && (test_protocol == FILE_TEST || test_protocol == MK_TEST || test_protocol == HTTP_TEST)) { ok(bindf == (BINDF_ASYNCHRONOUS|BINDF_ASYNCSTORAGE|BINDF_PULLDATA |BINDF_FROMURLMON), "bindf=%08x\n", bindf); @@ -513,7 +520,7 @@ static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, if(test_protocol == FILE_TEST) { hres = IInternetProtocolSink_ReportProgress(pOIProtSink, - BINDSTATUS_CACHEFILENAMEAVAILABLE, emptyW); + BINDSTATUS_CACHEFILENAMEAVAILABLE, INDEX_HTML+7); ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres); @@ -546,6 +553,8 @@ static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, if(test_protocol != FILE_TEST && test_protocol != MK_TEST) SET_EXPECT(Obj_OnProgress_MIMETYPEAVAILABLE); SET_EXPECT(Obj_OnProgress_BEGINDOWNLOADDATA); + if(test_protocol == FILE_TEST) + SET_EXPECT(Obj_OnProgress_CACHEFILENAMEAVAILABLE); SET_EXPECT(Obj_OnProgress_ENDDOWNLOADDATA); SET_EXPECT(Obj_OnProgress_CLASSIDAVAILABLE); SET_EXPECT(Obj_OnProgress_BEGINSYNCOPERATION); @@ -560,6 +569,8 @@ static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, if(test_protocol != FILE_TEST && test_protocol != MK_TEST) SET_EXPECT(OnProgress_MIMETYPEAVAILABLE); SET_EXPECT(OnProgress_BEGINDOWNLOADDATA); + if(test_protocol == FILE_TEST) + SET_EXPECT(OnProgress_CACHEFILENAMEAVAILABLE); SET_EXPECT(OnProgress_ENDDOWNLOADDATA); SET_EXPECT(LockRequest); SET_EXPECT(OnDataAvailable); @@ -574,6 +585,8 @@ static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, if(test_protocol != FILE_TEST && test_protocol != MK_TEST) CHECK_CALLED(Obj_OnProgress_MIMETYPEAVAILABLE); CHECK_CALLED(Obj_OnProgress_BEGINDOWNLOADDATA); + if(test_protocol == FILE_TEST) + CHECK_CALLED(Obj_OnProgress_CACHEFILENAMEAVAILABLE); CHECK_CALLED(Obj_OnProgress_ENDDOWNLOADDATA); CHECK_CALLED(Obj_OnProgress_CLASSIDAVAILABLE); CHECK_CALLED(Obj_OnProgress_BEGINSYNCOPERATION); @@ -588,6 +601,8 @@ static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, if(test_protocol != FILE_TEST && test_protocol != MK_TEST) CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE); CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA); + if(test_protocol == FILE_TEST) + CHECK_CALLED(OnProgress_CACHEFILENAMEAVAILABLE); CHECK_CALLED(OnProgress_ENDDOWNLOADDATA); CHECK_CALLED(LockRequest); CHECK_CALLED(OnDataAvailable); @@ -648,6 +663,13 @@ static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface, ok(hres == S_OK, "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres); + if(tymed == TYMED_FILE) { + hres = IInternetProtocolSink_ReportProgress(protocol_sink, + BINDSTATUS_CACHEFILENAMEAVAILABLE, cache_fileW); + ok(hres == S_OK, + "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres); + } + bscf |= BSCF_FIRSTDATANOTIFICATION; break; } @@ -1160,6 +1182,17 @@ static HRESULT WINAPI statusclb_OnProgress(IBindStatusCallback *iface, ULONG ulP download_state = END_DOWNLOAD; break; case BINDSTATUS_CACHEFILENAMEAVAILABLE: + trace("%s\n", debugstr_w(szStatusText)); + if(test_protocol != HTTP_TEST) { + if(iface == &objbsc) + CHECK_EXPECT(Obj_OnProgress_CACHEFILENAMEAVAILABLE); + else + CHECK_EXPECT(OnProgress_CACHEFILENAMEAVAILABLE); + }else { /* FIXME */ + CLEAR_CALLED(OnProgress_CACHEFILENAMEAVAILABLE); + CLEAR_CALLED(Obj_OnProgress_CACHEFILENAMEAVAILABLE); + } + ok(szStatusText != NULL, "szStatusText == NULL\n"); if(szStatusText && test_protocol == FILE_TEST) ok(!lstrcmpW(INDEX_HTML+7, szStatusText), "wrong szStatusText\n"); @@ -1279,36 +1312,42 @@ static HRESULT WINAPI statusclb_OnDataAvailable(IBindStatusCallback *iface, DWOR ok(pformatetc->ptd == NULL, "ptd = %p\n", pformatetc->ptd); ok(pformatetc->dwAspect == 1, "dwAspect=%u\n", pformatetc->dwAspect); ok(pformatetc->lindex == -1, "lindex=%d\n", pformatetc->lindex); - ok(pformatetc->tymed == TYMED_ISTREAM, "tymed=%u\n", pformatetc->tymed); + ok(pformatetc->tymed == tymed, "tymed=%u, expected %u\n", pformatetc->tymed, tymed); } ok(pstgmed != NULL, "stgmeg == NULL\n"); - if(!pstgmed) { - skip("further pstgmed related tests here.\n"); - return S_OK; - } - ok(pstgmed->tymed == TYMED_ISTREAM, "tymed=%u\n", pstgmed->tymed); - ok(U(*pstgmed).pstm != NULL, "pstm == NULL\n"); + ok(pstgmed->tymed == tymed, "tymed=%u, expected %u\n", pstgmed->tymed, tymed); ok(pstgmed->pUnkForRelease != NULL, "pUnkForRelease == NULL\n"); - if(grfBSCF & BSCF_FIRSTDATANOTIFICATION) { - hres = IStream_Write(U(*pstgmed).pstm, buf, 10, NULL); - ok(hres == STG_E_ACCESSDENIED, - "Write failed: %08x, expected STG_E_ACCESSDENIED\n", hres); - - hres = IStream_Commit(U(*pstgmed).pstm, 0); - ok(hres == E_NOTIMPL, "Commit failed: %08x, expected E_NOTIMPL\n", hres); + switch(pstgmed->tymed) { + case TYMED_ISTREAM: + if(grfBSCF & BSCF_FIRSTDATANOTIFICATION) { + hres = IStream_Write(U(*pstgmed).pstm, buf, 10, NULL); + ok(hres == STG_E_ACCESSDENIED, + "Write failed: %08x, expected STG_E_ACCESSDENIED\n", hres); - hres = IStream_Revert(U(*pstgmed).pstm); - ok(hres == E_NOTIMPL, "Revert failed: %08x, expected E_NOTIMPL\n", hres); - } + hres = IStream_Commit(U(*pstgmed).pstm, 0); + ok(hres == E_NOTIMPL, "Commit failed: %08x, expected E_NOTIMPL\n", hres); - ok(U(*pstgmed).pstm != NULL, "U(*pstgmed).pstm == NULL\n"); + hres = IStream_Revert(U(*pstgmed).pstm); + ok(hres == E_NOTIMPL, "Revert failed: %08x, expected E_NOTIMPL\n", hres); + } - if(U(*pstgmed).pstm) { + ok(U(*pstgmed).pstm != NULL, "U(*pstgmed).pstm == NULL\n"); do hres = IStream_Read(U(*pstgmed).pstm, buf, 512, &readed); while(hres == S_OK); ok(hres == S_FALSE || hres == E_PENDING, "IStream_Read returned %08x\n", hres); + break; + + case TYMED_FILE: + if(test_protocol == FILE_TEST) + ok(!lstrcmpW(pstgmed->u.lpszFileName, INDEX_HTML+7), + "unexpected file name %s\n", debugstr_w(pstgmed->u.lpszFileName)); + else if(emulate_protocol) + ok(!lstrcmpW(pstgmed->u.lpszFileName, cache_fileW), + "unexpected file name %s\n", debugstr_w(pstgmed->u.lpszFileName)); + else + ok(pstgmed->u.lpszFileName != NULL, "lpszFileName == NULL\n"); } if(test_protocol == HTTP_TEST && emulate_protocol && prot_state < 4 && (!bind_to_object || prot_state > 1)) @@ -1327,9 +1366,6 @@ static HRESULT WINAPI statusclb_OnObjectAvailable(IBindStatusCallback *iface, RE ok(IsEqualGUID(&IID_IUnknown, riid), "riid = %s\n", debugstr_guid(riid)); ok(punk != NULL, "punk == NULL\n"); - if(0&&test_protocol == HTTP_TEST) - SetEvent(complete_event); - return S_OK; } @@ -1443,8 +1479,6 @@ static HRESULT WINAPI PersistMoniker_Load(IPersistMoniker *iface, BOOL fFullyAva CHECK_EXPECT(Load); ok(GetCurrentThreadId() == thread_id, "wrong thread %d\n", GetCurrentThreadId()); - trace("LOAD %p\n", pibc); - if(test_protocol == HTTP_TEST) ok(!fFullyAvailable, "fFulyAvailable = %x\n", fFullyAvailable); else @@ -1472,9 +1506,9 @@ static HRESULT WINAPI PersistMoniker_Load(IPersistMoniker *iface, BOOL fFullyAva SET_EXPECT(GetBindInfo); SET_EXPECT(OnStartBinding); - if(test_protocol == FILE_TEST) - SET_EXPECT(OnProgress_MIMETYPEAVAILABLE); SET_EXPECT(OnProgress_BEGINDOWNLOADDATA); + if(test_protocol == FILE_TEST) + SET_EXPECT(OnProgress_CACHEFILENAMEAVAILABLE); if(test_protocol != HTTP_TEST) SET_EXPECT(OnProgress_ENDDOWNLOADDATA); SET_EXPECT(LockRequest); @@ -1487,9 +1521,9 @@ static HRESULT WINAPI PersistMoniker_Load(IPersistMoniker *iface, BOOL fFullyAva CHECK_CALLED(GetBindInfo); CHECK_CALLED(OnStartBinding); - if(test_protocol == FILE_TEST) - todo_wine CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE); CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA); + if(test_protocol == FILE_TEST) + CHECK_CALLED(OnProgress_CACHEFILENAMEAVAILABLE); if(test_protocol != HTTP_TEST) CHECK_CALLED(OnProgress_ENDDOWNLOADDATA); CHECK_CALLED(LockRequest); @@ -1898,7 +1932,7 @@ static void test_RegisterBindStatusCallback(void) IBindCtx_Release(bindctx); } -static void init_bind_test(int protocol, BOOL emul, BOOL bto) +static void init_bind_test(int protocol, BOOL emul, BOOL bto, DWORD t) { test_protocol = protocol; emulate_protocol = emul; @@ -1909,9 +1943,10 @@ static void init_bind_test(int protocol, BOOL emul, BOOL bto) mime_type[0] = 0; binding_hres = S_OK; bind_to_object = bto; + tymed = t; } -static void test_BindToStorage(int protocol, BOOL emul) +static void test_BindToStorage(int protocol, BOOL emul, DWORD t) { IMoniker *mon; HRESULT hres; @@ -1922,7 +1957,7 @@ static void test_BindToStorage(int protocol, BOOL emul) IUnknown *unk = (IUnknown*)0x00ff00ff; IBinding *bind; - init_bind_test(protocol, emul, FALSE); + init_bind_test(protocol, emul, FALSE, t); SET_EXPECT(QueryInterface_IServiceProvider); hres = CreateAsyncBindCtx(0, &bsc, NULL, &bctx); @@ -1960,6 +1995,9 @@ static void test_BindToStorage(int protocol, BOOL emul) "GetDisplayName got wrong name %s\n", debugstr_w(display_name)); CoTaskMemFree(display_name); + if(tymed == TYMED_FILE && (test_protocol == ABOUT_TEST || test_protocol == ITS_TEST)) + binding_hres = INET_E_DATA_NOT_AVAILABLE; + SET_EXPECT(GetBindInfo); SET_EXPECT(QueryInterface_IInternetProtocol); if(!emulate_protocol) @@ -1969,9 +2007,12 @@ static void test_BindToStorage(int protocol, BOOL emul) SET_EXPECT(Start); if(test_protocol == HTTP_TEST) SET_EXPECT(Terminate); - SET_EXPECT(UnlockRequest); + if(tymed != TYMED_FILE || (test_protocol != ABOUT_TEST && test_protocol != ITS_TEST)) + SET_EXPECT(UnlockRequest); }else { if(test_protocol == HTTP_TEST) { + SET_EXPECT(QueryInterface_IInternetBindInfo); + SET_EXPECT(QueryService_IInternetBindInfo); SET_EXPECT(QueryInterface_IHttpNegotiate); SET_EXPECT(BeginningTransaction); SET_EXPECT(QueryInterface_IHttpNegotiate2); @@ -1985,24 +2026,31 @@ static void test_BindToStorage(int protocol, BOOL emul) SET_EXPECT(OnResponse); SET_EXPECT(OnProgress_MIMETYPEAVAILABLE); SET_EXPECT(OnProgress_BEGINDOWNLOADDATA); + if(test_protocol == FILE_TEST) + SET_EXPECT(OnProgress_CACHEFILENAMEAVAILABLE); if(test_protocol == HTTP_TEST) SET_EXPECT(OnProgress_DOWNLOADINGDATA); SET_EXPECT(OnProgress_ENDDOWNLOADDATA); - SET_EXPECT(OnDataAvailable); + if(tymed != TYMED_FILE || test_protocol != ABOUT_TEST) + SET_EXPECT(OnDataAvailable); SET_EXPECT(OnStopBinding); } - hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&unk); + hres = IMoniker_BindToStorage(mon, bctx, NULL, tymed == TYMED_ISTREAM ? &IID_IStream : &IID_IUnknown, (void**)&unk); if (test_protocol == HTTP_TEST && hres == HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED)) { - trace( "Network unreachable, skipping tests\n" ); + skip("Network unreachable, skipping tests\n"); return; } - if (!SUCCEEDED(hres)) return; - if((bindf & BINDF_ASYNCHRONOUS) && !data_available) { + if(((bindf & BINDF_ASYNCHRONOUS) && !data_available) + || (tymed == TYMED_FILE && test_protocol == FILE_TEST)) { ok(hres == MK_S_ASYNCHRONOUS, "IMoniker_BindToStorage failed: %08x\n", hres); ok(unk == NULL, "istr should be NULL\n"); + }else if(tymed == TYMED_FILE && test_protocol == ABOUT_TEST) { + ok(hres == INET_E_DATA_NOT_AVAILABLE, + "IMoniker_BindToStorage failed: %08x, expected INET_E_DATA_NOT_AVAILABLE\n", hres); + ok(unk == NULL, "istr should be NULL\n"); }else { ok(hres == S_OK, "IMoniker_BindToStorage failed: %08x\n", hres); ok(unk != NULL, "unk == NULL\n"); @@ -2010,6 +2058,9 @@ static void test_BindToStorage(int protocol, BOOL emul) if(unk) IUnknown_Release(unk); + if(FAILED(hres)) + return; + while((bindf & BINDF_ASYNCHRONOUS) && !stopped_binding && GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); @@ -2023,11 +2074,17 @@ static void test_BindToStorage(int protocol, BOOL emul) CHECK_CALLED(OnStartBinding); if(emulate_protocol) { CHECK_CALLED(Start); - if(test_protocol == HTTP_TEST) + if(test_protocol == HTTP_TEST) { + if(tymed == TYMED_FILE) + CLEAR_CALLED(Read); CHECK_CALLED(Terminate); - CHECK_CALLED(UnlockRequest); + } + if(tymed != TYMED_FILE || (test_protocol != ABOUT_TEST && test_protocol != ITS_TEST)) + CHECK_CALLED(UnlockRequest); }else { if(test_protocol == HTTP_TEST) { + CLEAR_CALLED(QueryInterface_IInternetBindInfo); + CLEAR_CALLED(QueryService_IInternetBindInfo); CHECK_CALLED(QueryInterface_IHttpNegotiate); CHECK_CALLED(BeginningTransaction); /* QueryInterface_IHttpNegotiate2 and GetRootSecurityId @@ -2048,10 +2105,13 @@ static void test_BindToStorage(int protocol, BOOL emul) CHECK_CALLED(OnResponse); CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE); CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA); + if(test_protocol == FILE_TEST) + CHECK_CALLED(OnProgress_CACHEFILENAMEAVAILABLE); if(test_protocol == HTTP_TEST) CLEAR_CALLED(OnProgress_DOWNLOADINGDATA); CHECK_CALLED(OnProgress_ENDDOWNLOADDATA); - CHECK_CALLED(OnDataAvailable); + if(tymed != TYMED_FILE || test_protocol != ABOUT_TEST) + CHECK_CALLED(OnDataAvailable); CHECK_CALLED(OnStopBinding); } @@ -2073,7 +2133,7 @@ static void test_BindToObject(int protocol, BOOL emul) IUnknown *unk = (IUnknown*)0x00ff00ff; IBinding *bind; - init_bind_test(protocol, emul, TRUE); + init_bind_test(protocol, emul, TRUE, TYMED_ISTREAM); if(emul) CoRegisterClassObject(&CLSID_HTMLDocument, (IUnknown *)&mime_cf, @@ -2130,6 +2190,8 @@ static void test_BindToObject(int protocol, BOOL emul) SET_EXPECT(OnResponse); SET_EXPECT(Obj_OnProgress_MIMETYPEAVAILABLE); SET_EXPECT(Obj_OnProgress_BEGINDOWNLOADDATA); + if(test_protocol == FILE_TEST) + SET_EXPECT(Obj_OnProgress_CACHEFILENAMEAVAILABLE); if(test_protocol == HTTP_TEST) SET_EXPECT(OnProgress_DOWNLOADINGDATA); SET_EXPECT(Obj_OnProgress_ENDDOWNLOADDATA); @@ -2195,12 +2257,18 @@ static void test_BindToObject(int protocol, BOOL emul) CHECK_NOT_CALLED(Obj_OnProgress_CONNECTING); } } - if(test_protocol == HTTP_TEST || test_protocol == FILE_TEST) - CHECK_CALLED(Obj_OnProgress_SENDINGREQUEST); + if(test_protocol == HTTP_TEST || test_protocol == FILE_TEST) { + if(urls[test_protocol] == SHORT_RESPONSE_URL) + CLEAR_CALLED(Obj_OnProgress_SENDINGREQUEST); + else + CHECK_CALLED(Obj_OnProgress_SENDINGREQUEST); + } if(test_protocol == HTTP_TEST) CHECK_CALLED(OnResponse); CHECK_CALLED(Obj_OnProgress_MIMETYPEAVAILABLE); CHECK_CALLED(Obj_OnProgress_BEGINDOWNLOADDATA); + if(test_protocol == FILE_TEST) + CHECK_CALLED(Obj_OnProgress_CACHEFILENAMEAVAILABLE); if(test_protocol == HTTP_TEST) CLEAR_CALLED(OnProgress_DOWNLOADINGDATA); CLEAR_CALLED(Obj_OnProgress_ENDDOWNLOADDATA); @@ -2266,7 +2334,7 @@ static void test_ReportResult(HRESULT exhres) IUnknown *unk = (void*)0xdeadbeef; HRESULT hres; - init_bind_test(ABOUT_TEST, TRUE, FALSE); + init_bind_test(ABOUT_TEST, TRUE, FALSE, TYMED_ISTREAM); binding_hres = exhres; hres = CreateURLMoniker(NULL, ABOUT_BLANK, &mon); @@ -2284,9 +2352,10 @@ static void test_ReportResult(HRESULT exhres) hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&unk); if(SUCCEEDED(exhres)) - ok(hres == S_OK, "BindToStorage failed: %08x\n", hres); + ok(hres == S_OK || hres == MK_S_ASYNCHRONOUS, "BindToStorage failed: %08x\n", hres); else - ok(hres == exhres, "BindToStorage failed: %08x, expected %08x\n", hres, exhres); + ok(hres == exhres || hres == MK_S_ASYNCHRONOUS, + "BindToStorage failed: %08x, expected %08x or MK_S_ASYNCHRONOUS\n", hres, exhres); CHECK_CALLED(GetBindInfo); CHECK_CALLED(QueryInterface_IInternetProtocol); @@ -2315,7 +2384,8 @@ static void test_BindToStorage_fail(void) ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08x\n", hres); hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&unk); - ok(hres == MK_E_SYNTAX, "hres=%08x, expected INET_E_SYNTAX\n", hres); + ok(hres == MK_E_SYNTAX || hres == INET_E_DATA_NOT_AVAILABLE, + "hres=%08x, expected MK_E_SYNTAX or INET_E_DATA_NOT_AVAILABLE\n", hres); IBindCtx_Release(bctx); @@ -2325,8 +2395,40 @@ static void test_BindToStorage_fail(void) test_ReportResult(S_FALSE); } +static void gecko_installer_workaround(BOOL disable) +{ + HKEY hkey; + DWORD res; + + static BOOL has_url = FALSE; + static char url[2048]; + + if(!disable && !has_url) + return; + + res = RegOpenKey(HKEY_CURRENT_USER, "Software\\Wine\\MSHTML", &hkey); + if(res != ERROR_SUCCESS) + return; + + if(disable) { + DWORD type, size = sizeof(url); + + res = RegQueryValueEx(hkey, "GeckoUrl", NULL, &type, (PVOID)url, &size); + if(res == ERROR_SUCCESS && type == REG_SZ) + has_url = TRUE; + + RegDeleteValue(hkey, "GeckoUrl"); + }else { + RegSetValueEx(hkey, "GeckoUrl", 0, REG_SZ, (PVOID)url, lstrlenA(url)+1); + } + + RegCloseKey(hkey); +} + START_TEST(url) { + gecko_installer_workaround(TRUE); + complete_event = CreateEvent(NULL, FALSE, FALSE, NULL); complete_event2 = CreateEvent(NULL, FALSE, FALSE, NULL); thread_id = GetCurrentThreadId(); @@ -2338,60 +2440,99 @@ START_TEST(url) test_BindToStorage_fail(); trace("synchronous http test (COM not initialised)...\n"); - test_BindToStorage(HTTP_TEST, FALSE); + test_BindToStorage(HTTP_TEST, FALSE, TYMED_ISTREAM); CoInitialize(NULL); trace("synchronous http test...\n"); - test_BindToStorage(HTTP_TEST, FALSE); + test_BindToStorage(HTTP_TEST, FALSE, TYMED_ISTREAM); + + trace("synchronous http test (to object)...\n"); test_BindToObject(HTTP_TEST, FALSE); trace("synchronous file test...\n"); create_file(); - test_BindToStorage(FILE_TEST, FALSE); + test_BindToStorage(FILE_TEST, FALSE, TYMED_ISTREAM); + + trace("synchronous file test (to object)...\n"); test_BindToObject(FILE_TEST, FALSE); DeleteFileW(wszIndexHtml); bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA; trace("http test...\n"); - test_BindToStorage(HTTP_TEST, FALSE); + test_BindToStorage(HTTP_TEST, FALSE, TYMED_ISTREAM); + + trace("http test (to file)...\n"); + test_BindToStorage(HTTP_TEST, FALSE, TYMED_FILE); + + trace("http test (to object)...\n"); test_BindToObject(HTTP_TEST, FALSE); trace("http test (short response)...\n"); http_is_first = TRUE; urls[HTTP_TEST] = SHORT_RESPONSE_URL; - test_BindToStorage(HTTP_TEST, FALSE); + test_BindToStorage(HTTP_TEST, FALSE, TYMED_ISTREAM); + + trace("http test (short response, to object)...\n"); test_BindToObject(HTTP_TEST, FALSE); trace("emulated http test...\n"); - test_BindToStorage(HTTP_TEST, TRUE); + test_BindToStorage(HTTP_TEST, TRUE, TYMED_ISTREAM); + + trace("emulated http test (to object)...\n"); test_BindToObject(HTTP_TEST, TRUE); + trace("emulated http test (to file)...\n"); + test_BindToStorage(HTTP_TEST, TRUE, TYMED_FILE); + trace("about test...\n"); - test_BindToStorage(ABOUT_TEST, FALSE); + test_BindToStorage(ABOUT_TEST, FALSE, TYMED_ISTREAM); + + trace("about test (to file)...\n"); + test_BindToStorage(ABOUT_TEST, FALSE, TYMED_FILE); + + trace("about test (to object)...\n"); test_BindToObject(ABOUT_TEST, FALSE); trace("emulated about test...\n"); - test_BindToStorage(ABOUT_TEST, TRUE); + test_BindToStorage(ABOUT_TEST, TRUE, TYMED_ISTREAM); + + trace("emulated about test (to file)...\n"); + test_BindToStorage(ABOUT_TEST, TRUE, TYMED_FILE); + + trace("emulated about test (to object)...\n"); test_BindToObject(ABOUT_TEST, TRUE); trace("file test...\n"); create_file(); - test_BindToStorage(FILE_TEST, FALSE); + test_BindToStorage(FILE_TEST, FALSE, TYMED_ISTREAM); + + trace("file test (to file)...\n"); + test_BindToStorage(FILE_TEST, FALSE, TYMED_FILE); + + trace("file test (to object)...\n"); test_BindToObject(FILE_TEST, FALSE); DeleteFileW(wszIndexHtml); trace("emulated file test...\n"); set_file_url(); - test_BindToStorage(FILE_TEST, TRUE); + test_BindToStorage(FILE_TEST, TRUE, TYMED_ISTREAM); + + trace("emulated file test (to file)...\n"); + test_BindToStorage(FILE_TEST, TRUE, TYMED_FILE); + + trace("emulated file test (to object)...\n"); test_BindToObject(FILE_TEST, TRUE); trace("emulated its test...\n"); - test_BindToStorage(ITS_TEST, TRUE); + test_BindToStorage(ITS_TEST, TRUE, TYMED_ISTREAM); + + trace("emulated its test (to file)...\n"); + test_BindToStorage(ITS_TEST, TRUE, TYMED_FILE); trace("emulated mk test...\n"); - test_BindToStorage(MK_TEST, TRUE); + test_BindToStorage(MK_TEST, TRUE, TYMED_ISTREAM); trace("test failures...\n"); test_BindToStorage_fail(); @@ -2399,4 +2540,6 @@ START_TEST(url) CloseHandle(complete_event); CloseHandle(complete_event2); CoUninitialize(); + + gecko_installer_workaround(FALSE); } diff --git a/dlls/urlmon/umon.c b/dlls/urlmon/umon.c index 5981a1c96d0..640f3821be0 100644 --- a/dlls/urlmon/umon.c +++ b/dlls/urlmon/umon.c @@ -1186,6 +1186,27 @@ HRESULT WINAPI BindAsyncMoniker(IMoniker *pmk, DWORD grfOpt, IBindStatusCallback } /*********************************************************************** + * MkParseDisplayNameEx (URLMON.@) + */ +HRESULT WINAPI MkParseDisplayNameEx(IBindCtx *pbc, LPCWSTR szDisplayName, ULONG *pchEaten, LPMONIKER *ppmk) +{ + TRACE("(%p %s %p %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk); + + if(is_registered_protocol(szDisplayName)) { + HRESULT hres; + + hres = CreateURLMoniker(NULL, szDisplayName, ppmk); + if(SUCCEEDED(hres)) { + *pchEaten = strlenW(szDisplayName); + return hres; + } + } + + return MkParseDisplayName(pbc, szDisplayName, pchEaten, ppmk); +} + + +/*********************************************************************** * URLDownloadToFileA (URLMON.@) * * Downloads URL szURL to rile szFileName and call lpfnCB callback to diff --git a/dlls/urlmon/urlmon.spec b/dlls/urlmon/urlmon.spec index fdb94eb0123..1fa2f941c34 100644 --- a/dlls/urlmon/urlmon.spec +++ b/dlls/urlmon/urlmon.spec @@ -21,7 +21,7 @@ @ stdcall CoInternetQueryInfo(ptr long long ptr long ptr long) @ stub CompareSecurityIds @ stub CopyBindInfo -@ stub CopyStgMedium +@ stdcall CopyStgMedium(ptr ptr) @ stdcall CreateAsyncBindCtx(long ptr ptr ptr) @ stdcall CreateAsyncBindCtxEx(ptr long ptr ptr ptr long) @ stdcall CreateFormatEnumerator(long ptr ptr) @@ -53,7 +53,7 @@ @ stub IsLoggingEnabledA @ stub IsLoggingEnabledW @ stdcall IsValidURL(ptr wstr long) -@ stdcall MkParseDisplayNameEx(ptr ptr ptr ptr) ole32.MkParseDisplayName +@ stdcall MkParseDisplayNameEx(ptr wstr ptr ptr) @ stdcall ObtainUserAgentString(long str ptr) @ stub PrivateCoInstall @ stdcall RegisterBindStatusCallback(ptr ptr ptr long) diff --git a/dlls/urlmon/urlmon_main.c b/dlls/urlmon/urlmon_main.c index 1661bb66c2d..ca52143345e 100644 --- a/dlls/urlmon/urlmon_main.c +++ b/dlls/urlmon/urlmon_main.c @@ -406,6 +406,39 @@ void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo) pbindinfo->cbSize = size; } +/*********************************************************************** + * CopyStgMedium (URLMON.@) + */ +HRESULT WINAPI CopyStgMedium(const STGMEDIUM *src, STGMEDIUM *dst) +{ + TRACE("(%p %p)\n", src, dst); + + if(!src || !dst) + return E_POINTER; + + memcpy(dst, src, sizeof(STGMEDIUM)); + + switch(dst->tymed) { + case TYMED_NULL: + break; + case TYMED_ISTREAM: + if(dst->u.pstm) + IStream_AddRef(dst->u.pstm); + break; + case TYMED_ISTORAGE: + if(dst->u.pstg) + IStorage_AddRef(dst->u.pstg); + break; + default: + FIXME("Unimplemented tymed %d\n", src->tymed); + } + + if(dst->pUnkForRelease) + IUnknown_AddRef(dst->pUnkForRelease); + + return S_OK; +} + static BOOL text_richtext_filter(const BYTE *b, DWORD size) { return size > 5 && !memcmp(b, "{\\rtf", 5); @@ -604,16 +637,25 @@ HRESULT WINAPI FindMimeFromData(LPBC pBC, LPCWSTR pwzUrl, LPVOID pBuffer, } mime_filters[] = { {wszTextHtml, text_html_filter}, {wszTextRichtext, text_richtext_filter}, + /* {wszAudioXAiff, audio_xaiff_filter}, */ + /* {wszAudioBasic, audio_basic_filter}, */ {wszAudioWav, audio_wav_filter}, {wszImageGif, image_gif_filter}, {wszImagePjpeg, image_pjpeg_filter}, {wszImageTiff, image_tiff_filter}, {wszImageXPng, image_xpng_filter}, + /* {wszImageXBitmap, image_xbitmap_filter}, */ {wszImageBmp, image_bmp_filter}, + /* {wszImageXJg, image_xjg_filter}, */ + /* {wszImageXEmf, image_xemf_filter}, */ + /* {wszImageXWmf, image_xwmf_filter}, */ {wszVideoAvi, video_avi_filter}, {wszVideoMpeg, video_mpeg_filter}, {wszAppPostscript, application_postscript_filter}, + /* {wszAppBase64, application_base64_filter}, */ + /* {wszAppMacbinhex40, application_macbinhex40_filter}, */ {wszAppPdf, application_pdf_filter}, + /* {wszAppXCompressed, application_xcompressed_filter}, */ {wszAppXZip, application_xzip_filter}, {wszAppXGzip, application_xgzip_filter}, {wszAppJava, application_java_filter}, diff --git a/dlls/urlmon/urlmon_main.h b/dlls/urlmon/urlmon_main.h index d845e6e0feb..87e74f903b1 100644 --- a/dlls/urlmon/urlmon_main.h +++ b/dlls/urlmon/urlmon_main.h @@ -67,6 +67,7 @@ void UMCloseCacheFileStream(IUMCacheStream *pstr); IInternetProtocolInfo *get_protocol_info(LPCWSTR url); HRESULT get_protocol_handler(LPCWSTR url, CLSID *clsid, IClassFactory **ret); +BOOL is_registered_protocol(LPCWSTR); HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv); HRESULT bind_to_object(IMoniker *mon, LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv); diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c index c39d08ba329..cd788913332 100644 --- a/dlls/user32/combo.c +++ b/dlls/user32/combo.c @@ -435,14 +435,11 @@ static void CBCalcPlacement( if (lprEdit->right < lprEdit->left) lprEdit->right = lprEdit->left; - TRACE("\ttext\t= (%d,%d-%d,%d)\n", - lprEdit->left, lprEdit->top, lprEdit->right, lprEdit->bottom); + TRACE("\ttext\t= (%s)\n", wine_dbgstr_rect(lprEdit)); - TRACE("\tbutton\t= (%d,%d-%d,%d)\n", - lprButton->left, lprButton->top, lprButton->right, lprButton->bottom); + TRACE("\tbutton\t= (%s)\n", wine_dbgstr_rect(lprButton)); - TRACE("\tlbox\t= (%d,%d-%d,%d)\n", - lprLB->left, lprLB->top, lprLB->right, lprLB->bottom ); + TRACE("\tlbox\t= (%s)\n", wine_dbgstr_rect(lprLB)); } /*********************************************************************** diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c index 2bde5adf0ba..53caf12162e 100644 --- a/dlls/user32/defwnd.c +++ b/dlls/user32/defwnd.c @@ -421,8 +421,8 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa GetClientRect( hwnd, &rc ); x = (rc.right - rc.left - GetSystemMetrics(SM_CXICON))/2; y = (rc.bottom - rc.top - GetSystemMetrics(SM_CYICON))/2; - TRACE("Painting class icon: vis rect=(%d,%d - %d,%d)\n", - ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom ); + TRACE("Painting class icon: vis rect=(%s)\n", + wine_dbgstr_rect(&ps.rcPaint)); DrawIcon( hdc, x, y, hIcon ); } EndPaint( hwnd, &ps ); diff --git a/dlls/user32/display.drv.spec b/dlls/user32/display.drv.spec index 82af0e50366..2a805d699a2 100644 --- a/dlls/user32/display.drv.spec +++ b/dlls/user32/display.drv.spec @@ -27,7 +27,7 @@ 25 stub GetPaletteTranslate 26 stub UpdateColors 27 stub StretchBlt -28 stub StrechDIBits +28 stub StretchDIBits 29 stub SelectBitmap 30 stub BitmapBits 31 stub ReEnable diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c index ed010a80ef4..4354e055e22 100644 --- a/dlls/user32/hook.c +++ b/dlls/user32/hook.c @@ -314,7 +314,7 @@ static LRESULT call_hook_proc( HOOKPROC proc, INT id, INT code, WPARAM wparam, L * * Retrieve the hook procedure real value for a module-relative proc */ -static void *get_hook_proc( void *proc, const WCHAR *module ) +void *get_hook_proc( void *proc, const WCHAR *module ) { HMODULE mod; diff --git a/dlls/user32/listbox.c b/dlls/user32/listbox.c index d819684c2cb..72326442bf1 100644 --- a/dlls/user32/listbox.c +++ b/dlls/user32/listbox.c @@ -581,9 +581,9 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect, if (!IsWindowEnabled(descr->self)) dis.itemState |= ODS_DISABLED; dis.itemData = item->data; dis.rcItem = *rect; - TRACE("[%p]: drawitem %d (%s) action=%02x state=%02x rect=%d,%d-%d,%d\n", + TRACE("[%p]: drawitem %d (%s) action=%02x state=%02x rect=%s\n", descr->self, index, item ? debugstr_w(item->str) : "", action, - dis.itemState, rect->left, rect->top, rect->right, rect->bottom ); + dis.itemState, wine_dbgstr_rect(rect) ); SendMessageW(descr->owner, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis); } else @@ -601,9 +601,9 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect, oldText = SetTextColor( hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); } - TRACE("[%p]: painting %d (%s) action=%02x rect=%d,%d-%d,%d\n", + TRACE("[%p]: painting %d (%s) action=%02x rect=%s\n", descr->self, index, item ? debugstr_w(item->str) : "", action, - rect->left, rect->top, rect->right, rect->bottom ); + wine_dbgstr_rect(rect) ); if (!item) ExtTextOutW( hdc, rect->left + 1, rect->top, ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL ); diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index 99c4933e9c6..660c5d58c2b 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -4252,7 +4252,7 @@ END: * EndMenu (USER.187) * EndMenu (USER32.@) */ -void WINAPI EndMenu(void) +BOOL WINAPI EndMenu(void) { /* if we are in the menu code, and it is active */ if (!fEndMenu && top_popup) @@ -4266,6 +4266,7 @@ void WINAPI EndMenu(void) /* don't end up with an orphaned menu */ PostMessageW( top_popup, WM_CANCELMODE, 0, 0); } + return fEndMenu; } diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 67bf10e81e6..eb0168f70ce 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -1987,25 +1987,6 @@ static inline void call_sendmsg_callback( SENDASYNCPROC callback, HWND hwnd, UIN /*********************************************************************** - * get_hook_proc - * - * Retrieve the hook procedure real value for a module-relative proc - */ -static void *get_hook_proc( void *proc, const WCHAR *module ) -{ - HMODULE mod; - - if (!(mod = GetModuleHandleW(module))) - { - TRACE( "loading %s\n", debugstr_w(module) ); - /* FIXME: the library will never be freed */ - if (!(mod = LoadLibraryW(module))) return NULL; - } - return (char *)mod + (ULONG_PTR)proc; -} - - -/*********************************************************************** * peek_message * * Peek for a message matching the given parameters. Return FALSE if none available. diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c index 58671c5ac98..503f7c1a4c8 100644 --- a/dlls/user32/nonclient.c +++ b/dlls/user32/nonclient.c @@ -396,9 +396,7 @@ BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exSty WS_EX_STATICEDGE | WS_EX_TOOLWINDOW); if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME; - TRACE("(%d,%d)-(%d,%d) %08x %d %08x\n", - rect->left, rect->top, rect->right, rect->bottom, - style, menu, exStyle ); + TRACE("(%s) %08x %d %08x\n", wine_dbgstr_rect(rect), style, menu, exStyle ); NC_AdjustRectOuter( rect, style, menu, exStyle ); NC_AdjustRectInner( rect, style, exStyle ); @@ -1065,14 +1063,12 @@ static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint ) RECT r = rect; r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); - TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n", - r.left, r.top, r.right, r.bottom); + TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r)); rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1; } - TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n", - rect.left, rect.top, rect.right, rect.bottom ); + TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect)); if (dwExStyle & WS_EX_CLIENTEDGE) DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c index 9ba4a7a863a..93fe97cf869 100644 --- a/dlls/user32/painting.c +++ b/dlls/user32/painting.c @@ -444,9 +444,8 @@ HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps ) lps->fErase = send_erase( hwnd, flags, hrgn, &lps->rcPaint, &lps->hdc ); - TRACE("hdc = %p box = (%d,%d - %d,%d), fErase = %d\n", - lps->hdc, lps->rcPaint.left, lps->rcPaint.top, lps->rcPaint.right, lps->rcPaint.bottom, - lps->fErase); + TRACE("hdc = %p box = (%s), fErase = %d\n", + lps->hdc, wine_dbgstr_rect(&lps->rcPaint), lps->fErase); return lps->hdc; } diff --git a/dlls/user32/spy.c b/dlls/user32/spy.c index 22a4d5c4882..b0a93ba55c6 100644 --- a/dlls/user32/spy.c +++ b/dlls/user32/spy.c @@ -2321,10 +2321,8 @@ static void SPY_DumpStructure(const SPY_INSTANCE *sp_e, BOOL enter) case LVM_GETSUBITEMRECT: { LPRECT rc = (LPRECT) sp_e->lParam; - if (rc) { - TRACE("lParam rect (%d,%d)-(%d,%d)\n", - rc->left, rc->top, rc->right, rc->bottom); - } + if (rc) + TRACE("lParam rect (%s)\n", wine_dbgstr_rect(rc)); break; } case LVM_SETITEMPOSITION32: @@ -2404,10 +2402,9 @@ static void SPY_DumpStructure(const SPY_INSTANCE *sp_e, BOOL enter) lpdis->CtlType, lpdis->CtlID); TRACE("itemID=0x%08x itemAction=0x%08x itemState=0x%08x\n", lpdis->itemID, lpdis->itemAction, lpdis->itemState); - TRACE("hWnd=%p hDC=%p (%d,%d)-(%d,%d) itemData=0x%08lx\n", - lpdis->hwndItem, lpdis->hDC, lpdis->rcItem.left, - lpdis->rcItem.top, lpdis->rcItem.right, - lpdis->rcItem.bottom, lpdis->itemData); + TRACE("hWnd=%p hDC=%p (%s) itemData=0x%08lx\n", + lpdis->hwndItem, lpdis->hDC, + wine_dbgstr_rect(&lpdis->rcItem), lpdis->itemData); } break; case WM_MEASUREITEM: @@ -2463,8 +2460,7 @@ static void SPY_DumpStructure(const SPY_INSTANCE *sp_e, BOOL enter) case WM_NCCALCSIZE: { RECT *rc = (RECT *)sp_e->lParam; - TRACE("Rect (%d,%d)-(%d,%d)\n", - rc->left, rc->top, rc->right, rc->bottom); + TRACE("Rect (%s)\n", wine_dbgstr_rect(rc)); } break; case WM_NOTIFY: diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c index b323a9be29f..e3554808a10 100644 --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -2107,7 +2107,13 @@ BOOL WINAPI SystemParametersInfoW( UINT uiAction, UINT uiParam, break; } - WINE_SPI_FIXME(SPI_SETMOUSESPEED); /* 113 _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */ + case SPI_SETMOUSESPEED: /* 113 _WIN32_WINNT >= 0x500 || _WIN32_WINDOW > 0x400 */ + { + ret = save_int_param( SPI_SETMOUSE_REGKEY, SPI_SETMOUSE_VALNAME3, + &mouse_speed, (INT) pvParam, fWinIni); + + break; + } case SPI_GETSCREENSAVERRUNNING: ret = get_bool_param( SPI_SETSCREENSAVERRUNNING_IDX, diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index 781282c279a..ca4b1185120 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -32,6 +32,174 @@ #include "wingdi.h" #include "winuser.h" +static char **test_argv; +static int test_argc; +static HWND child = 0; +static HWND parent = 0; +static HANDLE child_process; + +#define PROC_INIT (WM_USER+1) + +static LRESULT CALLBACK callback_child(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + BOOL ret; + DWORD error; + + switch (msg) + { + /* Destroy the cursor. */ + case WM_USER+1: + SetLastError(0xdeadbeef); + ret = DestroyCursor((HCURSOR) lParam); + error = GetLastError(); + todo_wine { + ok(!ret, "DestroyCursor on the active cursor succeeded.\n"); + ok(error == ERROR_DESTROY_OBJECT_OF_OTHER_THREAD, + "Last error: %u\n", error); + } + return TRUE; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +static LRESULT CALLBACK callback_parent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == PROC_INIT) + { + child = (HWND) wParam; + return TRUE; + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +static void do_child(void) +{ + WNDCLASS class; + MSG msg; + BOOL ret; + + /* Register a new class. */ + class.style = CS_GLOBALCLASS; + class.lpfnWndProc = callback_child; + class.cbClsExtra = 0; + class.cbWndExtra = 0; + class.hInstance = GetModuleHandle(NULL); + class.hIcon = NULL; + class.hCursor = NULL; + class.hbrBackground = NULL; + class.lpszMenuName = NULL; + class.lpszClassName = "cursor_child"; + + SetLastError(0xdeadbeef); + ret = RegisterClass(&class); + ok(ret, "Failed to register window class. Error: %u\n", GetLastError()); + + /* Create a window. */ + child = CreateWindowA("cursor_child", "cursor_child", WS_POPUP | WS_VISIBLE, + 0, 0, 200, 200, 0, 0, 0, NULL); + ok(child != 0, "CreateWindowA failed. Error: %u\n", GetLastError()); + + /* Let the parent know our HWND. */ + PostMessage(parent, PROC_INIT, (WPARAM) child, 0); + + /* Receive messages. */ + while ((ret = GetMessage(&msg, child, 0, 0))) + { + ok(ret != -1, "GetMessage failed. Error: %u\n", GetLastError()); + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +static void do_parent(void) +{ + char path_name[MAX_PATH]; + PROCESS_INFORMATION info; + STARTUPINFOA startup; + WNDCLASS class; + MSG msg; + BOOL ret; + + /* Register a new class. */ + class.style = CS_GLOBALCLASS; + class.lpfnWndProc = callback_parent; + class.cbClsExtra = 0; + class.cbWndExtra = 0; + class.hInstance = GetModuleHandle(NULL); + class.hIcon = NULL; + class.hCursor = NULL; + class.hbrBackground = NULL; + class.lpszMenuName = NULL; + class.lpszClassName = "cursor_parent"; + + SetLastError(0xdeadbeef); + ret = RegisterClass(&class); + ok(ret, "Failed to register window class. Error: %u\n", GetLastError()); + + /* Create a window. */ + parent = CreateWindowA("cursor_parent", "cursor_parent", WS_POPUP | WS_VISIBLE, + 0, 0, 200, 200, 0, 0, 0, NULL); + ok(parent != 0, "CreateWindowA failed. Error: %u\n", GetLastError()); + + /* Start child process. */ + memset(&startup, 0, sizeof(startup)); + startup.cb = sizeof(startup); + startup.dwFlags = STARTF_USESHOWWINDOW; + startup.wShowWindow = SW_SHOWNORMAL; + + sprintf(path_name, "%s cursoricon %x", test_argv[0], (unsigned int) parent); + ok(CreateProcessA(NULL, path_name, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess failed.\n"); + child_process = info.hProcess; + + /* Wait for child window handle. */ + while ((child == 0) && (ret = GetMessage(&msg, parent, 0, 0))) + { + ok(ret != -1, "GetMessage failed. Error: %u\n", GetLastError()); + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +static void finish_child_process(void) +{ + SendMessage(child, WM_CLOSE, 0, 0); + winetest_wait_child_process( child_process ); + CloseHandle(child_process); +} + +static void test_child_process(void) +{ + static const BYTE bmp_bits[4096]; + HCURSOR cursor; + ICONINFO cursorInfo; + UINT display_bpp; + HDC hdc; + + /* Create and set a dummy cursor. */ + hdc = GetDC(0); + display_bpp = GetDeviceCaps(hdc, BITSPIXEL); + ReleaseDC(0, hdc); + + cursorInfo.fIcon = FALSE; + cursorInfo.xHotspot = 0; + cursorInfo.yHotspot = 0; + cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits); + cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits); + + cursor = CreateIconIndirect(&cursorInfo); + ok(cursor != NULL, "CreateIconIndirect returned %p.\n", cursor); + + SetCursor(cursor); + + /* Destroy the cursor. */ + SendMessage(child, WM_USER+1, 0, (LPARAM) cursor); +} + static void test_CopyImage_Check(HBITMAP bitmap, UINT flags, INT copyWidth, INT copyHeight, INT expectedWidth, INT expectedHeight, WORD expectedDepth, BOOL dibExpected) { @@ -471,6 +639,21 @@ static void test_DestroyCursor(void) START_TEST(cursoricon) { + test_argc = winetest_get_mainargs(&test_argv); + + if (test_argc >= 3) + { + /* Child process. */ + sscanf (test_argv[2], "%x", (unsigned int *) &parent); + + ok(parent != NULL, "Parent not found.\n"); + if (parent == NULL) + ExitProcess(1); + + do_child(); + return; + } + test_CopyImage_Bitmap(1); test_CopyImage_Bitmap(4); test_CopyImage_Bitmap(8); @@ -480,4 +663,7 @@ START_TEST(cursoricon) test_initial_cursor(); test_CreateIcon(); test_DestroyCursor(); + do_parent(); + test_child_process(); + finish_child_process(); } diff --git a/dlls/user32/tests/listbox.c b/dlls/user32/tests/listbox.c index 3645190c52a..18b79515c87 100644 --- a/dlls/user32/tests/listbox.c +++ b/dlls/user32/tests/listbox.c @@ -559,6 +559,11 @@ static void test_listbox_LB_DIR() char pathBuffer[MAX_PATH]; char * p; char driveletter; + HANDLE file; + + file = CreateFileA( "wtest1.tmp.c", FILE_ALL_ACCESS, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL ); + ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d", GetLastError()); + CloseHandle( file ); /* NOTE: for this test to succeed, there must be no subdirectories under the current directory. In addition, there must be at least @@ -965,6 +970,8 @@ static void test_listbox_LB_DIR() ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); } DestroyWindow(hList); + + DeleteFileA( "wtest1.tmp.c" ); } HWND g_listBox; @@ -1045,6 +1052,11 @@ static void test_listbox_dlgdir(void) char tempBuffer[MAX_PATH]; char * p; char driveletter; + HANDLE file; + + file = CreateFileA( "wtest1.tmp.c", FILE_ALL_ACCESS, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL ); + ok(file != INVALID_HANDLE_VALUE, "Error creating the test file: %d", GetLastError()); + CloseHandle( file ); /* NOTE: for this test to succeed, there must be no subdirectories under the current directory. In addition, there must be at least @@ -1436,6 +1448,8 @@ static void test_listbox_dlgdir(void) } } DestroyWindow(hWnd); + + DeleteFileA( "wtest1.tmp.c" ); } START_TEST(listbox) diff --git a/dlls/user32/uitools.c b/dlls/user32/uitools.c index b2e1239b034..9e2c106fe2f 100644 --- a/dlls/user32/uitools.c +++ b/dlls/user32/uitools.c @@ -576,8 +576,7 @@ static BOOL UITOOLS95_DrawRectEdge(HDC hdc, LPRECT rc, */ BOOL WINAPI DrawEdge( HDC hdc, LPRECT rc, UINT edge, UINT flags ) { - TRACE("%p %d,%d-%d,%d %04x %04x\n", - hdc, rc->left, rc->top, rc->right, rc->bottom, edge, flags ); + TRACE("%p %s %04x %04x\n", hdc, wine_dbgstr_rect(rc), edge, flags ); if(flags & BF_DIAGONAL) return UITOOLS95_DrawDiagEdge(hdc, rc, edge, flags); diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index fee0f5ef607..01444182d0a 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -235,6 +235,7 @@ extern BOOL CLIPBOARD_ReleaseOwner(void) DECLSPEC_HIDDEN; extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL HOOK_IsHooked( INT id ) DECLSPEC_HIDDEN; extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN; +extern void *get_hook_proc( void *proc, const WCHAR *module ); extern LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN; extern BOOL map_wparam_AtoW( UINT message, WPARAM *wparam, enum wm_char_mapping mapping ) DECLSPEC_HIDDEN; extern LRESULT MSG_SendInternalMessageTimeout( DWORD dest_pid, DWORD dest_tid, diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 1eb15d65730..40ff927c28a 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -170,8 +170,7 @@ BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) if (ret) { MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 ); - TRACE( "hwnd %p (%d,%d)-(%d,%d)\n", - hwnd, rect->left, rect->top, rect->right, rect->bottom); + TRACE( "hwnd %p (%s)\n", hwnd, wine_dbgstr_rect(rect) ); } return ret; } diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c index 8b4e29af1c1..b5f661975fb 100644 --- a/dlls/uxtheme/tests/system.c +++ b/dlls/uxtheme/tests/system.c @@ -417,8 +417,10 @@ static void test_GetCurrentThemeName(void) /* Given number of characters for the theme name is too large */ SetLastError(0xdeadbeef); hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme), NULL, 0, NULL, 0); - todo_wine - ok( hRes == E_POINTER, "Expected E_POINTER, got 0x%08x\n", hRes); + if (bThemeActive) + ok( hRes == E_POINTER || hRes == S_OK, "Expected E_POINTER or S_OK, got 0x%08x\n", hRes); + else + ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes); ok( GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got 0x%08x\n", GetLastError()); diff --git a/dlls/version/info.c b/dlls/version/info.c index 935d0c1a1a7..2be1df789bc 100644 --- a/dlls/version/info.c +++ b/dlls/version/info.c @@ -252,6 +252,10 @@ static DWORD VERSION_GetFileVersionInfo_PE( LPCWSTR filename, DWORD datasize, LP if(!hModule) { WARN("Could not load %s\n", debugstr_w(filename)); + + if (GetLastError() == ERROR_BAD_EXE_FORMAT) + return 0xFFFFFFFF; + return 0; } hRsrc = FindResourceW(hModule, diff --git a/dlls/version/tests/info.c b/dlls/version/tests/info.c index be1852fc024..d31797aa58c 100644 --- a/dlls/version/tests/info.c +++ b/dlls/version/tests/info.c @@ -44,6 +44,18 @@ "ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3)" \ "expected, got %u\n", GetLastError()); +static void create_file(const CHAR *name) +{ + HANDLE file; + DWORD written; + + file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name); + WriteFile(file, name, strlen(name), &written, NULL); + WriteFile(file, "\n", strlen("\n"), &written, NULL); + CloseHandle(file); +} + static void test_info_size(void) { DWORD hdl, retval; char mypath[MAX_PATH] = ""; @@ -153,6 +165,19 @@ static void test_info_size(void) } else trace("skipping GetModuleFileNameA(NULL,..) failed\n"); + + create_file("test.txt"); + + /* no version info */ + SetLastError(0xdeadbeef); + hdl = 0xcafe; + retval = GetFileVersionInfoSizeA("test.txt", &hdl); + ok(retval == 0, "Expected 0, got %d\n", retval); + ok(hdl == 0, "Expected 0, got %d\n", hdl); + ok(GetLastError() == ERROR_RESOURCE_DATA_NOT_FOUND, + "Expected ERROR_RESOURCE_DATA_NOT_FOUND, got %d\n", GetLastError()); + + DeleteFileA("test.txt"); } static void VersionDwordLong2String(DWORDLONG Version, LPSTR lpszVerString) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 2117d1310b6..84516c30d0f 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -1713,18 +1713,30 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { static void shader_arb_select_depth_blt(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; - static GLuint vprogram_id = 0; - static GLuint fprogram_id = 0; - if (!vprogram_id) vprogram_id = create_arb_blt_vertex_program(gl_info); - GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vprogram_id)); + if (!This->depth_blt_vprogram_id) This->depth_blt_vprogram_id = create_arb_blt_vertex_program(gl_info); + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, This->depth_blt_vprogram_id)); glEnable(GL_VERTEX_PROGRAM_ARB); - if (!fprogram_id) fprogram_id = create_arb_blt_fragment_program(gl_info); - GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, fprogram_id)); + if (!This->depth_blt_fprogram_id) This->depth_blt_fprogram_id = create_arb_blt_fragment_program(gl_info); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, This->depth_blt_fprogram_id)); glEnable(GL_FRAGMENT_PROGRAM_ARB); } +static void shader_arb_destroy_depth_blt(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + WineD3D_GL_Info *gl_info = &This->adapter->gl_info; + + if(This->depth_blt_vprogram_id) { + GL_EXTCALL(glDeleteProgramsARB(1, &This->depth_blt_vprogram_id)); + This->depth_blt_vprogram_id = 0; + } + if(This->depth_blt_fprogram_id) { + GL_EXTCALL(glDeleteProgramsARB(1, &This->depth_blt_fprogram_id)); + This->depth_blt_fprogram_id = 0; + } +} + static void shader_arb_cleanup(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; @@ -1747,6 +1759,7 @@ static void shader_arb_destroy(IWineD3DBaseShader *iface) { const shader_backend_t arb_program_shader_backend = { &shader_arb_select, &shader_arb_select_depth_blt, + &shader_arb_destroy_depth_blt, &shader_arb_load_constants, &shader_arb_cleanup, &shader_arb_color_correction, diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index f4c101fdd31..e06d7f7039b 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -1098,6 +1098,7 @@ void shader_trace_init( static void shader_none_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {} static void shader_none_select_depth_blt(IWineD3DDevice *iface) {} +static void shader_none_destroy_depth_blt(IWineD3DDevice *iface) {} static void shader_none_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {} static void shader_none_cleanup(IWineD3DDevice *iface) {} static void shader_none_color_correction(SHADER_OPCODE_ARG* arg) {} @@ -1106,6 +1107,7 @@ static void shader_none_destroy(IWineD3DBaseShader *iface) {} const shader_backend_t none_shader_backend = { &shader_none_select, &shader_none_select_depth_blt, + &shader_none_destroy_depth_blt, &shader_none_load_constants, &shader_none_cleanup, &shader_none_color_correction, diff --git a/dlls/wined3d/basetexture.c b/dlls/wined3d/basetexture.c index a4ad82065f1..34b6cbab706 100644 --- a/dlls/wined3d/basetexture.c +++ b/dlls/wined3d/basetexture.c @@ -112,7 +112,17 @@ void WINAPI IWineD3DBaseTextureImpl_PreLoad(IWineD3DBaseTexture *ifac } void WINAPI IWineD3DBaseTextureImpl_UnLoad(IWineD3DBaseTexture *iface) { - IWineD3DResourceImpl_UnLoad((IWineD3DResource *)iface); + IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + + if(This->baseTexture.textureName) { + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); + glDeleteTextures(1, &This->baseTexture.textureName); + This->baseTexture.textureName = 0; + LEAVE_GL(); + } + This->baseTexture.dirty = TRUE; } WINED3DRESOURCETYPE WINAPI IWineD3DBaseTextureImpl_GetType(IWineD3DBaseTexture *iface) { @@ -364,6 +374,12 @@ static inline void apply_wrap(const GLint textureDimensions, const DWORD state, if(textureDimensions==GL_TEXTURE_CUBE_MAP_ARB) { /* Cubemaps are always set to clamp, regardless of the sampler state. */ wrapParm = GL_CLAMP_TO_EDGE; + } else if(textureDimensions==GL_TEXTURE_RECTANGLE_ARB) { + if(state == WINED3DTADDRESS_WRAP) { + wrapParm = GL_CLAMP_TO_EDGE; + } else { + wrapParm = stateLookup[WINELOOKUP_WARPPARAM][state - minLookup[WINELOOKUP_WARPPARAM]]; + } } else { wrapParm = stateLookup[WINELOOKUP_WARPPARAM][state - minLookup[WINELOOKUP_WARPPARAM]]; } diff --git a/dlls/wined3d/cubetexture.c b/dlls/wined3d/cubetexture.c index 6704b1737d0..9e0769d915a 100644 --- a/dlls/wined3d/cubetexture.c +++ b/dlls/wined3d/cubetexture.c @@ -161,7 +161,6 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { static void WINAPI IWineD3DCubeTextureImpl_UnLoad(IWineD3DCubeTexture *iface) { unsigned int i, j; IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; TRACE("(%p)\n", This); /* Unload all the surfaces and reset the texture name. If UnLoad was called on the @@ -175,13 +174,7 @@ static void WINAPI IWineD3DCubeTextureImpl_UnLoad(IWineD3DCubeTexture *iface) { } } - if(This->baseTexture.textureName) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - ENTER_GL(); - glDeleteTextures(1, &This->baseTexture.textureName); - This->baseTexture.textureName = 0; - LEAVE_GL(); - } + IWineD3DBaseTextureImpl_UnLoad((IWineD3DBaseTexture *) iface); } static WINED3DRESOURCETYPE WINAPI IWineD3DCubeTextureImpl_GetType(IWineD3DCubeTexture *iface) { diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 1ec8ea8825b..22cd5ddb438 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -207,92 +207,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnkno return WINED3D_OK; } -static void CreateVBO(IWineD3DVertexBufferImpl *object) { - IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */ - GLenum error, glUsage; - DWORD vboUsage = object->resource.usage; - if(object->Flags & VBFLAG_VBOCREATEFAIL) { - WARN("Creating a vbo failed once, not trying again\n"); - return; - } - - TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage)); - - /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */ - ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - ENTER_GL(); - - /* Make sure that the gl error is cleared. Do not use checkGLcall - * here because checkGLcall just prints a fixme and continues. However, - * if an error during VBO creation occurs we can fall back to non-vbo operation - * with full functionality(but performance loss) - */ - while(glGetError() != GL_NO_ERROR); - - /* Basically the FVF parameter passed to CreateVertexBuffer is no good - * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with - * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer - * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified - * to check if the rhw and color values are in the correct format. - */ - - GL_EXTCALL(glGenBuffersARB(1, &object->vbo)); - error = glGetError(); - if(object->vbo == 0 || error != GL_NO_ERROR) { - WARN("Failed to create a VBO with error %s (%#x)\n", debug_glerror(error), error); - goto error; - } - - GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo)); - error = glGetError(); - if(error != GL_NO_ERROR) { - WARN("Failed to bind the VBO with error %s (%#x)\n", debug_glerror(error), error); - goto error; - } - - /* Don't use static, because dx apps tend to update the buffer - * quite often even if they specify 0 usage. Because we always keep the local copy - * we never read from the vbo and can create a write only opengl buffer. - */ - switch(vboUsage & (WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC) ) { - case WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC: - case WINED3DUSAGE_DYNAMIC: - TRACE("Gl usage = GL_STREAM_DRAW\n"); - glUsage = GL_STREAM_DRAW_ARB; - break; - case WINED3DUSAGE_WRITEONLY: - default: - TRACE("Gl usage = GL_DYNAMIC_DRAW\n"); - glUsage = GL_DYNAMIC_DRAW_ARB; - break; - } - - /* Reserve memory for the buffer. The amount of data won't change - * so we are safe with calling glBufferData once with a NULL ptr and - * calling glBufferSubData on updates - */ - GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage)); - error = glGetError(); - if(error != GL_NO_ERROR) { - WARN("glBufferDataARB failed with error %s (%#x)\n", debug_glerror(error), error); - goto error; - } - object->vbo_size = object->resource.size; - object->vbo_usage = glUsage; - - LEAVE_GL(); - - return; - error: - /* Clean up all vbo init, but continue because we can work without a vbo :-) */ - FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n"); - if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo)); - object->vbo = 0; - object->Flags |= VBFLAG_VBOCREATEFAIL; - LEAVE_GL(); - return; -} - static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage, DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle, IUnknown *parent) { @@ -347,7 +261,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac } else if(dxVersion <= 7 && conv) { TRACE("Not creating a vbo because dxVersion is 7 and the fvf needs conversion\n"); } else { - CreateVBO(object); + object->Flags |= VBFLAG_CREATEVBO; } return WINED3D_OK; } @@ -3941,7 +3855,8 @@ process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCo * write correct opengl data into it. It's cheap and allows us to run drawStridedFast */ if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) { - CreateVBO(dest); + dest->Flags |= VBFLAG_CREATEVBO; + IWineD3DVertexBuffer_PreLoad((IWineD3DVertexBuffer *) dest); } if(dest->vbo) { @@ -4800,6 +4715,7 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa RECT vp_rect; WINED3DVIEWPORT *vp = &This->stateBlock->viewport; UINT drawable_width, drawable_height; + IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *) This->stencilBufferTarget; /* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the * drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true @@ -4858,6 +4774,26 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfa checkGLcall("glClearDepth"); glMask = glMask | GL_DEPTH_BUFFER_BIT; IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE)); + + if(This->depth_copy_state == WINED3D_DCS_COPY) { + if(vp->X != 0 || vp->Y != 0 || + vp->Width < depth_stencil->currentDesc.Width || vp->Height < depth_stencil->currentDesc.Height) { + depth_copy((IWineD3DDevice *) This); + } + else if(This->stateBlock->renderState[WINED3DRS_SCISSORTESTENABLE] && ( + This->stateBlock->scissorRect.left > 0 || This->stateBlock->scissorRect.top > 0 || + This->stateBlock->scissorRect.right < depth_stencil->currentDesc.Width || + This->stateBlock->scissorRect.bottom < depth_stencil->currentDesc.Height)) { + depth_copy((IWineD3DDevice *) This); + } + else if(Count > 0 && pRects && ( + pRects[0].x1 > 0 || pRects[0].y1 > 0 || + pRects[0].x2 < depth_stencil->currentDesc.Width || + pRects[0].y2 < depth_stencil->currentDesc.Height)) { + depth_copy((IWineD3DDevice *) This); + } + } + This->depth_copy_state = WINED3D_DCS_INITIAL; } if (Flags & WINED3DCLEAR_TARGET) { @@ -6766,7 +6702,7 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAM } surface->currentDesc.Width = pPresentationParameters->BackBufferWidth; surface->currentDesc.Height = pPresentationParameters->BackBufferHeight; - if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) { + if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) { surface->pow2Width = pPresentationParameters->BackBufferWidth; surface->pow2Height = pPresentationParameters->BackBufferHeight; } else { @@ -6774,6 +6710,11 @@ static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAM while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1; while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1; } + surface->glRect.left = 0; + surface->glRect.top = 0; + surface->glRect.right = surface->pow2Width; + surface->glRect.bottom = surface->pow2Height; + if(surface->glDescription.textureName) { ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); ENTER_GL(); @@ -6799,6 +6740,61 @@ static HRESULT WINAPI reset_unload_resources(IWineD3DResource *resource, void *d return S_OK; } +static void reset_fbo_state(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + unsigned int i; + + ENTER_GL(); + GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); + checkGLcall("glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)"); + + if (This->fbo) { + GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo)); + This->fbo = 0; + } + if (This->src_fbo) { + GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->src_fbo)); + This->src_fbo = 0; + } + if (This->dst_fbo) { + GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->dst_fbo)); + This->dst_fbo = 0; + } + checkGLcall("Tear down fbos\n"); + LEAVE_GL(); + + for (i = 0; i < GL_LIMITS(buffers); ++i) { + This->fbo_color_attachments[i] = NULL; + } + This->fbo_depth_attachment = NULL; +} + +static BOOL is_display_mode_supported(IWineD3DDeviceImpl *This, WINED3DPRESENT_PARAMETERS *pp) { + UINT i, count; + WINED3DDISPLAYMODE m; + HRESULT hr; + + /* All Windowed modes are supported, as is leaving the current mode */ + if(pp->Windowed) return TRUE; + if(!pp->BackBufferWidth) return TRUE; + if(!pp->BackBufferHeight) return TRUE; + + count = IWineD3D_GetAdapterModeCount(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN); + for(i = 0; i < count; i++) { + memset(&m, 0, sizeof(m)); + hr = IWineD3D_EnumAdapterModes(This->wineD3D, This->adapter->num, WINED3DFMT_UNKNOWN, i, &m); + if(FAILED(hr)) { + ERR("EnumAdapterModes failed\n"); + } + if(m.Width == pp->BackBufferWidth && m.Height == pp->BackBufferHeight) { + /* Mode found, it is supported */ + return TRUE; + } + } + /* Mode not found -> not supported */ + return FALSE; +} + static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; IWineD3DSwapChainImpl *swapchain; @@ -6806,6 +6802,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE BOOL DisplayModeChanged = FALSE; WINED3DDISPLAYMODE mode; IWineD3DBaseShaderImpl *shader; + IWineD3DSurfaceImpl *target; + UINT i; TRACE("(%p)\n", This); hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain); @@ -6814,6 +6812,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE return hr; } + if(!is_display_mode_supported(This, pPresentationParameters)) { + WARN("Rejecting Reset() call because the requested display mode is not supported\n"); + WARN("Requested mode: %d, %d\n", pPresentationParameters->BackBufferWidth, + pPresentationParameters->BackBufferHeight); + return WINED3DERR_INVALIDCALL; + } + /* Is it necessary to recreate the gl context? Actually every setting can be changed * on an existing gl context, so there's no real need for recreation. * @@ -6859,12 +6864,39 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE ERR("What do do about a changed auto depth stencil parameter?\n"); } + if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { + reset_fbo_state((IWineD3DDevice *) This); + } + IWineD3DDevice_EnumResources(iface, reset_unload_resources, NULL); LIST_FOR_EACH_ENTRY(shader, &This->shaders, IWineD3DBaseShaderImpl, baseShader.shader_list_entry) { This->shader_backend->shader_destroy((IWineD3DBaseShader *) shader); } - if(pPresentationParameters->Windowed) { + ENTER_GL(); + if(This->depth_blt_texture) { + glDeleteTextures(1, &This->depth_blt_texture); + This->depth_blt_texture = 0; + } + This->shader_backend->shader_destroy_depth_blt(iface); + + for (i = 0; i < GL_LIMITS(textures); i++) { + /* The stateblock initialization below will recreate them */ + glDeleteTextures(1, &This->dummyTextureName[i]); + checkGLcall("glDeleteTextures(1, &This->dummyTextureName[i])"); + This->dummyTextureName[i] = 0; + } + LEAVE_GL(); + + while(This->numContexts) { + DestroyContext(This, This->contexts[0]); + } + This->activeContext = NULL; + HeapFree(GetProcessHeap(), 0, swapchain->context); + swapchain->context = NULL; + swapchain->num_contexts = 0; + + if(pPresentationParameters->Windowed) { mode.Width = swapchain->orig_width; mode.Height = swapchain->orig_height; mode.RefreshRate = 0; @@ -6906,6 +6938,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) { updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters); } + if(This->auto_depth_stencil_buffer) { + updateSurfaceDesc((IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer, pPresentationParameters); + } + /* Now set the new viewport */ IWineD3DDevice_SetViewport(iface, &vp); @@ -6927,7 +6963,39 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE IWineD3DDevice_SetFullscreen(iface, FALSE); } swapchain->presentParms.Windowed = pPresentationParameters->Windowed; + } else if(!pPresentationParameters->Windowed) { + DWORD style = This->style, exStyle = This->exStyle; + /* If we're in fullscreen, and the mode wasn't changed, we have to get the window back into + * the right position. Some applications(Battlefield 2, Guild Wars) move it and then call + * Reset to clear up their mess. Guild Wars also loses the device during that. + */ + This->style = 0; + This->exStyle = 0; + IWineD3DDeviceImpl_SetupFullscreenWindow(iface, This->ddraw_window); + This->style = style; + This->exStyle = exStyle; + } + + /* Recreate the primary swapchain's context */ + swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context)); + if(swapchain->backBuffer) { + target = (IWineD3DSurfaceImpl *) swapchain->backBuffer[0]; + } else { + target = (IWineD3DSurfaceImpl *) swapchain->frontBuffer; } + swapchain->context[0] = CreateContext(This, target, swapchain->win_handle, FALSE, + &swapchain->presentParms); + swapchain->num_contexts = 1; + This->activeContext = swapchain->context[0]; + + hr = IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *) This->stateBlock); + if(FAILED(hr)) { + ERR("Resetting the stateblock failed with error 0x%08x\n", hr); + } + + /* All done. There is no need to reload resources or shaders, this will happen automatically on the + * first use + */ IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain); return WINED3D_OK; diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index afd012ae499..3c9ea69dde2 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -512,6 +512,25 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { gl_string = (const char *) glGetString(GL_VERSION); if (gl_string != NULL) { + /* First, parse the generic opengl version. This is supposed not to be convoluted with + * driver specific information + */ + gl_string_cursor = gl_string; + major = atoi(gl_string_cursor); + if(major <= 0) { + ERR("Invalid opengl major version: %d\n", major); + } + while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') { + ++gl_string_cursor; + } + if (*gl_string_cursor++ != '.') { + ERR_(d3d_caps)("Invalid opengl version string: %s\n", debugstr_a(gl_string)); + } + minor = atoi(gl_string_cursor); + TRACE_(d3d_caps)("Found OpenGL version: %d.%d\n", major, minor); + gl_info->gl_version = MAKEDWORD_VERSION(major, minor); + + /* Now parse the driver specific string which we'll report to the app */ switch (gl_info->gl_vendor) { case VENDOR_NVIDIA: gl_string_cursor = strstr(gl_string, "NVIDIA"); @@ -635,8 +654,14 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { major = 0; minor = 9; } - gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor); - TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version); + gl_info->driver_version = MAKEDWORD_VERSION(major, minor); + TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version); + /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */ + gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14); + } else { + FIXME("OpenGL driver did not return version information\n"); + gl_info->driver_version = MAKEDWORD_VERSION(0, 0); + gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14); } TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card); @@ -726,7 +751,7 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { #define USE_GL_FUNC(type, pfn, ext, replace) { \ DWORD ver = ver_for_ext(ext); \ if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \ - else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \ + else if(ver && ver <= gl_info->gl_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \ else gl_info->pfn = NULL; \ } GL_EXT_FUNCS_GEN; @@ -742,7 +767,7 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { */ for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) { if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE && - EXTENSION_MAP[i].version <= gl_info->gl_driver_version && EXTENSION_MAP[i].version) { + EXTENSION_MAP[i].version <= gl_info->gl_version && EXTENSION_MAP[i].version) { TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string); gl_info->supported[EXTENSION_MAP[i].extension] = TRUE; } @@ -1531,9 +1556,8 @@ static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Ad /* Note dx8 doesn't supply a DeviceName */ if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */ - /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */ - pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14); - pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version; + pIdentifier->DriverVersion->u.HighPart = Adapters[Adapter].gl_info.driver_version_hipart; + pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.driver_version; *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor; *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card; *(pIdentifier->SubSysId) = 0; @@ -1903,22 +1927,12 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt return WINED3DERR_NOTAVAILABLE; } - if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { - switch (CheckFormat) { - case WINED3DFMT_DXT1: - case WINED3DFMT_DXT2: - case WINED3DFMT_DXT3: - case WINED3DFMT_DXT4: - case WINED3DFMT_DXT5: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - default: - break; /* Avoid compiler warnings */ + /* Check for supported sRGB formats (Texture loading and framebuffer) */ + if (Usage & WINED3DUSAGE_QUERY_SRGBREAD) { + if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) { + TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n"); } - } - /* Check for supported sRGB formats (Texture loading and framebuffer) */ - if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) { switch (CheckFormat) { case WINED3DFMT_A8R8G8B8: case WINED3DFMT_X8R8G8B8: @@ -1931,7 +1945,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt case WINED3DFMT_DXT4: case WINED3DFMT_DXT5: TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; + break; /* Continue with checking other flags */ default: TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat)); @@ -1939,23 +1953,6 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt } } - if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) { - - BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL); - - switch (CheckFormat) { - case WINED3DFMT_R16F: - case WINED3DFMT_A16B16G16R16F: - if (!half_pixel_support) break; - case WINED3DFMT_R32F: - case WINED3DFMT_A32B32G32R32F: - TRACE_(d3d_caps)("[OK]\n"); - return WINED3D_OK; - default: - break; /* Avoid compiler warnings */ - } - } - /* This format is nothing special and it is supported perfectly. * However, ati and nvidia driver on windows do not mark this format as * supported (tested with the dxCapsViewer) and pretending to @@ -2031,14 +2028,19 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt WARN_(d3d_caps)("[FAILED]\n"); return WINED3DERR_NOTAVAILABLE; - /***** - * DXTN Formats: Handled above - * WINED3DFMT_DXT1 - * WINED3DFMT_DXT2 - * WINED3DFMT_DXT3 - * WINED3DFMT_DXT4 - * WINED3DFMT_DXT5 - */ + case WINED3DFMT_DXT1: + case WINED3DFMT_DXT2: + case WINED3DFMT_DXT3: + case WINED3DFMT_DXT4: + case WINED3DFMT_DXT5: + if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { + TRACE_(d3d_caps)("[OK]\n"); + return WINED3D_OK; + } else { + TRACE_(d3d_caps)("[FAILED]\n"); + return WINED3DERR_NOTAVAILABLE; + } + /***** * Odd formats - not supported @@ -2051,10 +2053,8 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt return WINED3DERR_NOTAVAILABLE; /***** - * Float formats: Not supported right now + * WINED3DFMT_CxV8U8: Not supported right now */ - case WINED3DFMT_G16R16F: - case WINED3DFMT_G32R32F: case WINED3DFMT_CxV8U8: TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */ return WINED3DERR_NOTAVAILABLE; @@ -2065,6 +2065,31 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */ return WINED3DERR_NOTAVAILABLE; + /* Floating point formats */ + case WINED3DFMT_R16F: + case WINED3DFMT_A16B16G16R16F: + if(GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) { + TRACE_(d3d_caps)("[OK]\n"); + return WINED3D_OK; + } else { + TRACE_(d3d_caps)("[FAILED]\n"); + return WINED3DERR_NOTAVAILABLE; + } + case WINED3DFMT_R32F: + case WINED3DFMT_A32B32G32R32F: + if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) { + TRACE_(d3d_caps)("[OK]\n"); + return WINED3D_OK; + } else { + TRACE_(d3d_caps)("[FAILED]\n"); + return WINED3DERR_NOTAVAILABLE; + } + + case WINED3DFMT_G16R16F: + case WINED3DFMT_G32R32F: + TRACE_(d3d_caps)("[FAILED]\n"); + return WINED3DERR_NOTAVAILABLE; + /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support * instancing. To query if the card supports instancing CheckDeviceFormat with the special format * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value. @@ -2848,8 +2873,52 @@ static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) { } } +/* Certain applications(Steam) complain if we report an outdated driver version. In general, + * reporting a driver version is moot because we are not the Windows driver, and we have different + * bugs, features, etc. + * + * If a card is not found in this table, the gl driver version is reported + */ +struct driver_version_information { + WORD vendor; /* reported PCI card vendor ID */ + WORD card; /* reported PCI card device ID */ + WORD hipart_hi, hipart_lo; /* driver hiword to report */ + WORD lopart_hi, lopart_lo; /* driver loword to report */ +}; + +static const struct driver_version_information driver_version_table[] = { + /* Nvidia drivers. Geforce FX and newer cards are supported by the current driver */ + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, 7, 15, 10, 16921 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, 7, 15, 10, 16921 }, + + /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */ + {VENDOR_ATI, CARD_ATI_RADEON_9500, 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_X700, 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_X1600, 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2300, 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2600, 6, 14, 10, 6764 }, + {VENDOR_ATI, CARD_ATI_RADEON_HD2900, 6, 14, 10, 6764 }, + + /* TODO: Add information about legacy nvidia and ATI hardware, Intel and other cards */ +}; + static void fixup_extensions(WineD3D_GL_Info *gl_info) { - if(implementation_is_apple(gl_info)) { + unsigned int i; + BOOL apple = implementation_is_apple(gl_info); + + if(apple) { /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are * used it falls back to software. While the compiler can detect if the shader uses all declared * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader @@ -2894,6 +2963,20 @@ static void fixup_extensions(WineD3D_GL_Info *gl_info) { gl_info->set_texcoord_w = TRUE; } } + + /* Fixup the driver version */ + for(i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++) { + if(gl_info->gl_vendor == driver_version_table[i].vendor && + gl_info->gl_card == driver_version_table[i].card) { + TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card); + + gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi, + driver_version_table[i].lopart_lo); + gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi, + driver_version_table[i].hipart_lo); + break; + } + } } void invalid_func(void *data) { diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index 5d4d536d814..2ece34997f5 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -757,7 +757,7 @@ static void depth_blt(IWineD3DDevice *iface, GLuint texture) { This->shader_backend->shader_select(iface, use_ps(This), use_vs(This)); } -static void depth_copy(IWineD3DDevice *iface) { +void depth_copy(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *)This->auto_depth_stencil_buffer; @@ -773,20 +773,19 @@ static void depth_copy(IWineD3DDevice *iface) { } if (This->render_offscreen) { - static GLuint tmp_texture = 0; GLint old_binding = 0; TRACE("Copying onscreen depth buffer to offscreen surface\n"); - if (!tmp_texture) { - glGenTextures(1, &tmp_texture); + if (!This->depth_blt_texture) { + glGenTextures(1, &This->depth_blt_texture); } /* Note that we use depth_blt here as well, rather than glCopyTexImage2D * directly on the FBO texture. That's because we need to flip. */ GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding); - glBindTexture(GL_TEXTURE_2D, tmp_texture); + glBindTexture(GL_TEXTURE_2D, This->depth_blt_texture); glCopyTexImage2D(depth_stencil->glDescription.target, depth_stencil->glDescription.level, depth_stencil->glDescription.glFormatInternal, @@ -802,7 +801,7 @@ static void depth_copy(IWineD3DDevice *iface) { GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo)); checkGLcall("glBindFramebuffer()"); - depth_blt(iface, tmp_texture); + depth_blt(iface, This->depth_blt_texture); checkGLcall("depth_blt"); } else { TRACE("Copying offscreen surface to onscreen depth buffer\n"); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 64ca8b1629a..5572231d42b 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -3229,18 +3229,27 @@ static void shader_glsl_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { static void shader_glsl_select_depth_blt(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; - static GLhandleARB program_id = 0; static GLhandleARB loc = -1; - if (!program_id) { - program_id = create_glsl_blt_shader(gl_info); - loc = GL_EXTCALL(glGetUniformLocationARB(program_id, "sampler")); + if (!This->depth_blt_glsl_program_id) { + This->depth_blt_glsl_program_id = create_glsl_blt_shader(gl_info); + loc = GL_EXTCALL(glGetUniformLocationARB(This->depth_blt_glsl_program_id, "sampler")); } - GL_EXTCALL(glUseProgramObjectARB(program_id)); + GL_EXTCALL(glUseProgramObjectARB(This->depth_blt_glsl_program_id)); GL_EXTCALL(glUniform1iARB(loc, 0)); } +static void shader_glsl_destroy_depth_blt(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + WineD3D_GL_Info *gl_info = &This->adapter->gl_info; + + if(This->depth_blt_glsl_program_id) { + GL_EXTCALL(glDeleteObjectARB(This->depth_blt_glsl_program_id)); + This->depth_blt_glsl_program_id = 0; + } +} + static void shader_glsl_cleanup(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; WineD3D_GL_Info *gl_info = &This->adapter->gl_info; @@ -3285,6 +3294,7 @@ static void shader_glsl_destroy(IWineD3DBaseShader *iface) { const shader_backend_t glsl_shader_backend = { &shader_glsl_select, &shader_glsl_select_depth_blt, + &shader_glsl_destroy_depth_blt, &shader_glsl_load_constants, &shader_glsl_cleanup, &shader_glsl_color_correction, diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index cfb47cad81b..bd7308927ab 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -55,7 +55,8 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) { return; } - if(This->Flags & SFLAG_CONVERTED) { + /* Only support read back of converted P8 surfaces */ + if(This->Flags & SFLAG_CONVERTED && (This->resource.format != WINED3DFMT_P8)) { FIXME("Read back converted textures unsupported, format=%s\n", debug_d3dformat(This->resource.format)); return; } @@ -86,9 +87,17 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) { LEAVE_GL(); } else { void *mem; + GLenum format = This->glDescription.glFormat; + GLenum type = This->glDescription.glType; int src_pitch = 0; int dst_pitch = 0; + /* In case of P8 the index is stored in the alpha component if the primary render target uses P8 */ + if(This->resource.format == WINED3DFMT_P8) { + format = GL_ALPHA; + type = GL_UNSIGNED_BYTE; + } + if (This->Flags & SFLAG_NONPOW2) { unsigned char alignment = This->resource.wineD3DDevice->surface_alignment; src_pitch = This->bytesPerPixel * This->pow2Width; @@ -100,21 +109,21 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) { } TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level, - This->glDescription.glFormat, This->glDescription.glType, mem); + format, type, mem); if(This->Flags & SFLAG_PBO) { GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo)); checkGLcall("glBindBufferARB"); - glGetTexImage(This->glDescription.target, This->glDescription.level, This->glDescription.glFormat, - This->glDescription.glType, NULL); + glGetTexImage(This->glDescription.target, This->glDescription.level, format, + type, NULL); checkGLcall("glGetTexImage()"); GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0)); checkGLcall("glBindBufferARB"); } else { - glGetTexImage(This->glDescription.target, This->glDescription.level, This->glDescription.glFormat, - This->glDescription.glType, mem); + glGetTexImage(This->glDescription.target, This->glDescription.level, format, + type, mem); checkGLcall("glGetTexImage()"); } LEAVE_GL(); @@ -510,25 +519,43 @@ static void surface_remove_pbo(IWineD3DSurfaceImpl *This) { static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) { IWineD3DBaseTexture *texture = NULL; IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + renderbuffer_entry_t *entry, *entry2; TRACE("(%p)\n", iface); - /* Default pool resources are supposed to be destroyed before Reset is called. - * Implicit resources stay however. So this means we have an implicit render target - * or depth stencil, and the content isn't supposed to survive the reset anyway - */ if(This->resource.pool == WINED3DPOOL_DEFAULT) { - TRACE("Default pool - nothing to do\n"); - return; + /* Default pool resources are supposed to be destroyed before Reset is called. + * Implicit resources stay however. So this means we have an implicit render target + * or depth stencil. The content may be destroyed, but we still have to tear down + * opengl resources, so we cannot leave early. + */ + IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE); + } else { + /* Load the surface into system memory */ + IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); } - - /* Load the surface into system memory */ - IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); + IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE); + IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE); + This->Flags &= ~SFLAG_ALLOCATED; /* Destroy PBOs, but load them into real sysmem before */ if(This->Flags & SFLAG_PBO) { surface_remove_pbo(This); } + /* Destroy fbo render buffers. This is needed for implicit render targets, for + * all application-created targets the application has to release the surface + * before calling _Reset + */ + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) { + ENTER_GL(); + GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id)); + LEAVE_GL(); + list_remove(&entry->entry); + HeapFree(GetProcessHeap(), 0, entry); + } + list_init(&This->renderbuffers); + This->current_renderbuffer = NULL; + /* If we're in a texture, the texture name belongs to the texture. Otherwise, * destroy it */ @@ -1372,7 +1399,7 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ } } else if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { - *format = GL_RED; + *format = GL_ALPHA; *internal = GL_RGBA; *type = GL_UNSIGNED_BYTE; *target_bpp = 1; @@ -1912,15 +1939,14 @@ static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4] table[i][1] = device->palettes[device->currentPalette][i].peGreen; table[i][2] = device->palettes[device->currentPalette][i].peBlue; - if(index_in_alpha) { + /* BltOverride uses a GL_ALPHA_TEST based on GL_NOT_EQUAL 0, so the alpha component + of pixels that should be masked away should be 0. When inde_in_alpha is set, + we will store the palette index (the glReadPixels code reads GL_ALPHA back) + or else we store 0xff. */ + if(colorkey && (i >= This->SrcBltCKey.dwColorSpaceLowValue) && (i <= This->SrcBltCKey.dwColorSpaceHighValue)) { + table[i][3] = 0; + } else if(index_in_alpha) { table[i][3] = i; - } else if (colorkey && - (i >= This->SrcBltCKey.dwColorSpaceLowValue) && - (i <= This->SrcBltCKey.dwColorSpaceHighValue)) { - /* We should maybe here put a more 'neutral' color than the standard bright purple - one often used by application to prevent the nice purple borders when bi-linear - filtering is on */ - table[i][3] = 0x00; } else { table[i][3] = 0xFF; } @@ -1933,16 +1959,14 @@ static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4] table[i][1] = pal->palents[i].peGreen; table[i][2] = pal->palents[i].peBlue; - if(index_in_alpha) { - table[i][3] = i; - } - else if (colorkey && - (i >= This->SrcBltCKey.dwColorSpaceLowValue) && - (i <= This->SrcBltCKey.dwColorSpaceHighValue)) { - /* We should maybe here put a more 'neutral' color than the standard bright purple - one often used by application to prevent the nice purple borders when bi-linear - filtering is on */ + /* BltOverride uses a GL_ALPHA_TEST based on GL_NOT_EQUAL 0, so the alpha component + of pixels that should be masked away should be 0. When inde_in_alpha is set, + we will store the palette index (the glReadPixels code reads GL_ALPHA back) + or else we store 0xff. */ + if(colorkey && (i >= This->SrcBltCKey.dwColorSpaceLowValue) && (i <= This->SrcBltCKey.dwColorSpaceHighValue)) { table[i][3] = 0x00; + } else if(index_in_alpha) { + table[i][3] = i; } else if(pal->Flags & WINEDDPCAPS_ALPHA) { table[i][3] = pal->palents[i].peFlags; } else { @@ -1956,9 +1980,9 @@ const char *fragment_palette_conversion = "!!ARBfp1.0\n" "TEMP index;\n" "PARAM constants = { 0.996, 0.00195, 0, 0 };\n" /* { 255/256, 0.5/255*255/256, 0, 0 } */ - "TEX index.x, fragment.texcoord[0], texture[0], 2D;\n" /* store the red-component of the current pixel */ - "MAD index.x, index.x, constants.x, constants.y;\n" /* Scale the index by 255/256 and add a bias of '0.5' in order to sample in the middle */ - "TEX result.color, index, texture[1], 1D;\n" /* use the red-component as a index in the palette to get the final color */ + "TEX index, fragment.texcoord[0], texture[0], 2D;\n" /* The alpha-component contains the palette index */ + "MAD index.a, index.a, constants.x, constants.y;\n" /* Scale the index by 255/256 and add a bias of '0.5' in order to sample in the middle */ + "TEX result.color, index.a, texture[1], 1D;\n" /* use the alpha-component as a index in the palette to get the final color */ "END"; /* This function is used in case of 8bit paletted textures to upload the palette. @@ -2087,11 +2111,18 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface, BO /* To perform the color key conversion we need a sysmem copy of * the surface. Make sure we have it */ + IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); + /* Make sure the texture is reloaded because of the color key change, this kills performance though :( */ + /* TODO: This is not necessarily needed with hw palettized texture support */ + This->Flags &= ~SFLAG_INTEXTURE; } else if(palette9_changed(This)) { TRACE("Reloading surface because the d3d8/9 palette was changed\n"); /* TODO: This is not necessarily needed with hw palettized texture support */ IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); + + /* Make sure the texture is reloaded because of the color key change, this kills performance though :( */ + This->Flags &= ~SFLAG_INTEXTURE; } else { TRACE("surface is already in texture\n"); return WINED3D_OK; diff --git a/dlls/wined3d/surface_base.c b/dlls/wined3d/surface_base.c index 8a6f5469de7..d733852d30a 100644 --- a/dlls/wined3d/surface_base.c +++ b/dlls/wined3d/surface_base.c @@ -297,8 +297,9 @@ HRESULT WINAPI IWineD3DBaseSurfaceImpl_RealizePalette(IWineD3DSurface *iface) { if(This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) { - if(!This->Flags & SFLAG_INSYSMEM) { - FIXME("Palette changed with surface that does not have an up to date system memory copy\n"); + if(!(This->Flags & SFLAG_INSYSMEM)) { + TRACE("Palette changed with surface that does not have an up to date system memory copy\n"); + IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL); } TRACE("Dirtifying surface\n"); IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE); diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index fe37e554953..727636d3a53 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -145,7 +145,6 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { static void WINAPI IWineD3DTextureImpl_UnLoad(IWineD3DTexture *iface) { unsigned int i; IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; TRACE("(%p)\n", This); /* Unload all the surfaces and reset the texture name. If UnLoad was called on the @@ -157,13 +156,7 @@ static void WINAPI IWineD3DTextureImpl_UnLoad(IWineD3DTexture *iface) { IWineD3DSurface_SetGlTextureDesc(This->surfaces[i], 0, IWineD3DTexture_GetTextureDimensions(iface)); } - if(This->baseTexture.textureName) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - ENTER_GL(); - glDeleteTextures(1, &This->baseTexture.textureName); - This->baseTexture.textureName = 0; - LEAVE_GL(); - } + IWineD3DBaseTextureImpl_UnLoad((IWineD3DBaseTexture *) iface); } static WINED3DRESOURCETYPE WINAPI IWineD3DTextureImpl_GetType(IWineD3DTexture *iface) { diff --git a/dlls/wined3d/vertexbuffer.c b/dlls/wined3d/vertexbuffer.c index 1093addaa5b..72cef079cf5 100644 --- a/dlls/wined3d/vertexbuffer.c +++ b/dlls/wined3d/vertexbuffer.c @@ -406,6 +406,87 @@ static void check_vbo_size(IWineD3DVertexBufferImpl *This) { } } +static void CreateVBO(IWineD3DVertexBufferImpl *This) { + GLenum error, glUsage; + DWORD vboUsage = This->resource.usage; + IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + + TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", This, debug_d3dusage(vboUsage)); + + /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */ + ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + ENTER_GL(); + + /* Make sure that the gl error is cleared. Do not use checkGLcall + * here because checkGLcall just prints a fixme and continues. However, + * if an error during VBO creation occurs we can fall back to non-vbo operation + * with full functionality(but performance loss) + */ + while(glGetError() != GL_NO_ERROR); + + /* Basically the FVF parameter passed to CreateVertexBuffer is no good + * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with + * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer + * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified + * to check if the rhw and color values are in the correct format. + */ + + GL_EXTCALL(glGenBuffersARB(1, &This->vbo)); + error = glGetError(); + if(This->vbo == 0 || error != GL_NO_ERROR) { + WARN("Failed to create a VBO with error %s (%#x)\n", debug_glerror(error), error); + goto error; + } + + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, This->vbo)); + error = glGetError(); + if(error != GL_NO_ERROR) { + WARN("Failed to bind the VBO with error %s (%#x)\n", debug_glerror(error), error); + goto error; + } + + /* Don't use static, because dx apps tend to update the buffer + * quite often even if they specify 0 usage. Because we always keep the local copy + * we never read from the vbo and can create a write only opengl buffer. + */ + switch(vboUsage & (WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC) ) { + case WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC: + case WINED3DUSAGE_DYNAMIC: + TRACE("Gl usage = GL_STREAM_DRAW\n"); + glUsage = GL_STREAM_DRAW_ARB; + break; + case WINED3DUSAGE_WRITEONLY: + default: + TRACE("Gl usage = GL_DYNAMIC_DRAW\n"); + glUsage = GL_DYNAMIC_DRAW_ARB; + break; + } + + /* Reserve memory for the buffer. The amount of data won't change + * so we are safe with calling glBufferData once with a NULL ptr and + * calling glBufferSubData on updates + */ + GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, This->resource.size, NULL, glUsage)); + error = glGetError(); + if(error != GL_NO_ERROR) { + WARN("glBufferDataARB failed with error %s (%#x)\n", debug_glerror(error), error); + goto error; + } + This->vbo_size = This->resource.size; + This->vbo_usage = glUsage; + + LEAVE_GL(); + + return; + error: + /* Clean up all vbo init, but continue because we can work without a vbo :-) */ + FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n"); + if(This->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo)); + This->vbo = 0; + LEAVE_GL(); + return; +} + static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *iface) { IWineD3DVertexBufferImpl *This = (IWineD3DVertexBufferImpl *) iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; @@ -421,7 +502,12 @@ static void WINAPI IWineD3DVertexBufferImpl_PreLoad(IWineD3DVertexBuffer *if if(!This->vbo) { /* TODO: Make converting independent from VBOs */ - return; /* Not doing any conversion */ + if(This->Flags & VBFLAG_CREATEVBO) { + CreateVBO(This); + This->Flags &= ~VBFLAG_CREATEVBO; + } else { + return; /* Not doing any conversion */ + } } /* Reading the declaration makes only sense if the stateblock is finalized and the buffer bound to a stream */ @@ -612,6 +698,7 @@ static void WINAPI IWineD3DVertexBufferImpl_UnLoad(IWineD3DVertexBuffer *iface) checkGLcall("glDeleteBuffersARB"); LEAVE_GL(); This->vbo = 0; + This->Flags |= VBFLAG_CREATEVBO; /* Recreate the VBO next load */ } } diff --git a/dlls/wined3d/volumetexture.c b/dlls/wined3d/volumetexture.c index 9cddb4f1a4b..6639f9c7bbd 100644 --- a/dlls/wined3d/volumetexture.c +++ b/dlls/wined3d/volumetexture.c @@ -138,7 +138,6 @@ static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *ifac static void WINAPI IWineD3DVolumeTextureImpl_UnLoad(IWineD3DVolumeTexture *iface) { unsigned int i; IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; - IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; TRACE("(%p)\n", This); /* Unload all the surfaces and reset the texture name. If UnLoad was called on the @@ -149,13 +148,7 @@ static void WINAPI IWineD3DVolumeTextureImpl_UnLoad(IWineD3DVolumeTexture *iface IWineD3DVolume_UnLoad(This->volumes[i]); } - if(This->baseTexture.textureName) { - ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); - ENTER_GL(); - glDeleteTextures(1, &This->baseTexture.textureName); - This->baseTexture.textureName = 0; - LEAVE_GL(); - } + IWineD3DBaseTextureImpl_UnLoad((IWineD3DBaseTexture *) iface); } static WINED3DRESOURCETYPE WINAPI IWineD3DVolumeTextureImpl_GetType(IWineD3DVolumeTexture *iface) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 86f78693fa5..34de539e097 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -196,6 +196,7 @@ struct SHADER_OPCODE_ARG; typedef struct { void (*shader_select)(IWineD3DDevice *iface, BOOL usePS, BOOL useVS); void (*shader_select_depth_blt)(IWineD3DDevice *iface); + void (*shader_destroy_depth_blt)(IWineD3DDevice *iface); void (*shader_load_constants)(IWineD3DDevice *iface, char usePS, char useVS); void (*shader_cleanup)(IWineD3DDevice *iface); void (*shader_color_correction)(struct SHADER_OPCODE_ARG *arg); @@ -410,6 +411,8 @@ extern glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED]; #define GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_num) \ (((((d3dvtVertexType) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1) +void depth_copy(IWineD3DDevice *iface); + /* Routines and structures related to state management */ typedef struct WineD3DContext WineD3DContext; typedef void (*APPLYSTATEFUNC)(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *ctx); @@ -701,6 +704,10 @@ struct IWineD3DDeviceImpl GLuint src_fbo; GLuint dst_fbo; GLenum *draw_buffers; + GLuint depth_blt_texture; + GLuint depth_blt_vprogram_id; + GLuint depth_blt_fprogram_id; + GLhandleARB depth_blt_glsl_program_id; /* Cursor management */ BOOL bCursorVisible; @@ -881,7 +888,7 @@ extern const IWineD3DVertexBufferVtbl IWineD3DVertexBuffer_Vtbl; #define VBFLAG_OPTIMIZED 0x02 /* Optimize has been called for the VB */ #define VBFLAG_DIRTY 0x04 /* Buffer data has been modified */ #define VBFLAG_HASDESC 0x08 /* A vertex description has been found */ -#define VBFLAG_VBOCREATEFAIL 0x10 /* An attempt to create a vbo has failed */ +#define VBFLAG_CREATEVBO 0x10 /* Attempt to create a VBO next PreLoad */ /***************************************************************************** * IWineD3DIndexBuffer implementation structure (extends IWineD3DResourceImpl) @@ -1622,6 +1629,7 @@ unsigned int count_bits(unsigned int mask); extern DWORD WINAPI IWineD3DBaseTextureImpl_SetPriority(IWineD3DBaseTexture *iface, DWORD PriorityNew); extern DWORD WINAPI IWineD3DBaseTextureImpl_GetPriority(IWineD3DBaseTexture *iface); extern void WINAPI IWineD3DBaseTextureImpl_PreLoad(IWineD3DBaseTexture *iface); + extern void WINAPI IWineD3DBaseTextureImpl_UnLoad(IWineD3DBaseTexture *iface); extern WINED3DRESOURCETYPE WINAPI IWineD3DBaseTextureImpl_GetType(IWineD3DBaseTexture *iface); /*** IWineD3DBaseTexture methods ***/ extern DWORD WINAPI IWineD3DBaseTextureImpl_SetLOD(IWineD3DBaseTexture *iface, DWORD LODNew); diff --git a/dlls/winemp3.acm/interface.c b/dlls/winemp3.acm/interface.c index 2ac120ac067..336a4f801e9 100644 --- a/dlls/winemp3.acm/interface.c +++ b/dlls/winemp3.acm/interface.c @@ -204,13 +204,13 @@ int decodeMP3(struct mpstr *mp,const unsigned char *in,int isize,unsigned char * getbits(16); switch(mp->fr.lay) { case 1: - do_layer1(&mp->fr,(unsigned char *) out,done); + do_layer1(&mp->fr,out,done); break; case 2: - do_layer2(&mp->fr,(unsigned char *) out,done); + do_layer2(&mp->fr,out,done); break; case 3: - do_layer3(&mp->fr,(unsigned char *) out,done); + do_layer3(&mp->fr,out,done); break; } diff --git a/dlls/winemp3.acm/layer2.c b/dlls/winemp3.acm/layer2.c index d3cd46393e9..535d90c1f40 100644 --- a/dlls/winemp3.acm/layer2.c +++ b/dlls/winemp3.acm/layer2.c @@ -174,7 +174,7 @@ static void II_step_two(unsigned int *bit_alloc, real fraction[2][4][SBLIMIT], { static int *table[] = { 0,0,0,grp_3tab,0,grp_5tab,0,0,0,grp_9tab }; unsigned int idx,*tab,m=scale[x1]; - idx = (unsigned int) getbits(k); + idx = getbits(k); tab = (unsigned int *) (table[d1] + idx + idx + idx); fraction[j][0][i] = muls[*tab++][m]; fraction[j][1][i] = muls[*tab++][m]; @@ -209,7 +209,7 @@ static void II_step_two(unsigned int *bit_alloc, real fraction[2][4][SBLIMIT], static int *table[] = { 0,0,0,grp_3tab,0,grp_5tab,0,0,0,grp_9tab }; unsigned int idx,*tab,m1,m2; m1 = scale[x1]; m2 = scale[x1+3]; - idx = (unsigned int) getbits(k); + idx = getbits(k); tab = (unsigned int *) (table[d1] + idx + idx + idx); fraction[0][0][i] = muls[*tab][m1]; fraction[1][0][i] = muls[*tab++][m2]; fraction[0][1][i] = muls[*tab][m1]; fraction[1][1][i] = muls[*tab++][m2]; diff --git a/dlls/wineps.drv/driver.c b/dlls/wineps.drv/driver.c index b4f98fbf5de..42e537af511 100644 --- a/dlls/wineps.drv/driver.c +++ b/dlls/wineps.drv/driver.c @@ -550,8 +550,8 @@ DWORD PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszP LONG *lp = (LONG*)lpszOutput; if(lpszOutput != NULL) { - lp[0] = (LONG)pi->ppd->DefaultResolution; - lp[1] = (LONG)pi->ppd->DefaultResolution; + lp[0] = pi->ppd->DefaultResolution; + lp[1] = pi->ppd->DefaultResolution; } return 1; } diff --git a/dlls/wineps.drv/type1afm.c b/dlls/wineps.drv/type1afm.c index dd79eeedc48..dd7e0ce3176 100644 --- a/dlls/wineps.drv/type1afm.c +++ b/dlls/wineps.drv/type1afm.c @@ -861,7 +861,7 @@ static VOID Unicodify(AFM *afm, OLD_AFMMETRICS *metrics) { if (metrics[i].C >= 0x20 && metrics[i].C <= 0xff) { - metrics[i].UV = ((LONG)(metrics[i].C)) | 0xf000L; + metrics[i].UV = metrics[i].C | 0xf000L; } else { diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index ad861bb65fa..771a52bb8b3 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -681,8 +681,8 @@ static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage, register INT x, y; BOOL hstretch, vstretch, hswap, vswap; - hswap = ((int)widthSrc * widthDst) < 0; - vswap = ((int)heightSrc * heightDst) < 0; + hswap = widthSrc * widthDst < 0; + vswap = heightSrc * heightDst < 0; widthSrc = abs(widthSrc); heightSrc = abs(heightSrc); widthDst = abs(widthDst); @@ -708,7 +708,7 @@ static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage, if (hstretch) { - xinc = ((int)widthSrc << 16) / widthDst; + xinc = (widthSrc << 16) / widthDst; xoff = ((widthSrc << 16) - (xinc * widthDst)) / 2; } else @@ -720,7 +720,7 @@ static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage, wine_tsx11_lock(); if (vstretch) { - yinc = ((int)heightSrc << 16) / heightDst; + yinc = (heightSrc << 16) / heightDst; ydst = visRectDst->top; if (vswap) { @@ -778,7 +778,7 @@ static void BITBLT_StretchImage( XImage *srcImage, XImage *dstImage, } else /* Shrinking */ { - yinc = ((int)heightDst << 16) / heightSrc; + yinc = (heightDst << 16) / heightSrc; ysrc = visRectSrc->top; ydst = ((heightDst << 16) - (yinc * heightSrc)) / 2; if (vswap) diff --git a/dlls/winex11.drv/bitmap.c b/dlls/winex11.drv/bitmap.c index fffcab1727f..0bcb0871da3 100644 --- a/dlls/winex11.drv/bitmap.c +++ b/dlls/winex11.drv/bitmap.c @@ -122,9 +122,7 @@ BOOL X11DRV_CreateBitmap( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, LPVOID bmBit if (bitmap.bmPlanes != 1) return FALSE; /* check if bpp is compatible with screen depth */ - if (!((bitmap.bmBitsPixel == 1) || - (bitmap.bmBitsPixel == screen_bpp) || - (bitmap.bmBitsPixel == 16 && screen_bpp == 15))) /* TODO: Confirm this */ + if (!((bitmap.bmBitsPixel == 1) || (bitmap.bmBitsPixel == screen_bpp))) { ERR("Trying to make bitmap with planes=%d, bpp=%d\n", bitmap.bmPlanes, bitmap.bmBitsPixel); diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c index 453746f3a25..5e8599816af 100644 --- a/dlls/winex11.drv/clipboard.c +++ b/dlls/winex11.drv/clipboard.c @@ -1648,7 +1648,7 @@ HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget, Atom rpro memcpy(lpData, &lpdata->drvData, *lpBytes); GlobalUnlock(hData); - return (HANDLE) hData; + return hData; } @@ -1666,8 +1666,7 @@ HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget, Atom return 0; } - return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, (HANDLE)lpdata->hData32, - lpBytes, TRUE); + return X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, lpdata->hData32, lpBytes, TRUE); } @@ -1685,8 +1684,7 @@ HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget, Atom r return 0; } - return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, (HANDLE)lpdata->hData32, - lpBytes, TRUE); + return X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, lpdata->hData32, lpBytes, TRUE); } @@ -2136,7 +2134,7 @@ static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDW unsigned int wiresize, size; LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) GlobalLock(h); - memcpy(lpmfp, (LPVOID)hdata, sizeof(METAFILEPICT)); + memcpy(lpmfp, hdata, sizeof(METAFILEPICT)); wiresize = *lpcbytes - sizeof(METAFILEPICT); lpmfp->hMF = SetMetaFileBitsEx(wiresize, ((const BYTE *)hdata) + sizeof(METAFILEPICT)); @@ -2146,7 +2144,7 @@ static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDW } else if (wformat == CF_ENHMETAFILE) { - h = SetEnhMetaFileBits(*lpcbytes, (LPVOID)hdata); + h = SetEnhMetaFileBits(*lpcbytes, hdata); } } @@ -2990,7 +2988,7 @@ static void X11DRV_HandleSelectionRequest( HWND hWnd, XSelectionRequestEvent *ev wine_tsx11_lock(); XChangeProperty(display, request, rprop, event->target, - 8, PropModeReplace, (unsigned char *)lpClipData, cBytes); + 8, PropModeReplace, lpClipData, cBytes); wine_tsx11_unlock(); GlobalUnlock(hClipData); diff --git a/dlls/winex11.drv/dib.c b/dlls/winex11.drv/dib.c index a95783e5128..b05d90408e3 100644 --- a/dlls/winex11.drv/dib.c +++ b/dlls/winex11.drv/dib.c @@ -2643,7 +2643,7 @@ static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits, /* Windows only supports one 24bpp DIB format: RGB888 */ srcbits+=left*3; for (h = lines - 1; h >= 0; h--) { - srcbyte=(const BYTE*)srcbits; + srcbyte = srcbits; for (x = left; x < width+left; x++) { XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical @@ -4856,7 +4856,7 @@ HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc) * Create an HBITMAP with the same dimensions and BPP as the pixmap, * and make it a container for the pixmap passed. */ - hBmp = CreateBitmap( width, height, 1, depth, NULL ); + if (!(hBmp = CreateBitmap( width, height, 1, depth_to_bpp(depth), NULL ))) return 0; /* force bitmap to be owned by a screen DC */ hdcMem = CreateCompatibleDC( hdc ); diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 8e7eba45b84..ad42ef22f04 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -834,8 +834,8 @@ static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event ) if( lpDrop ) { WND *pDropWnd = WIN_GetPtr( hWnd ); lpDrop->pFiles = sizeof(DROPFILES); - lpDrop->pt.x = (INT)x; - lpDrop->pt.y = (INT)y; + lpDrop->pt.x = x; + lpDrop->pt.y = y; lpDrop->fNC = ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) || y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) || diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index c0d098adb59..3389d8b9f33 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1474,9 +1474,8 @@ void X11DRV_KeyEvent( HWND hwnd, XEvent *xev ) * X11 lock must be held. */ static void -X11DRV_KEYBOARD_DetectLayout (void) +X11DRV_KEYBOARD_DetectLayout( Display *display ) { - Display *display = thread_display(); unsigned current, match, mismatch, seq, i, syms; int score, keyc, key, pkey, ok; KeySym keysym = 0; @@ -1583,9 +1582,8 @@ X11DRV_KEYBOARD_DetectLayout (void) /********************************************************************** * X11DRV_InitKeyboard */ -void X11DRV_InitKeyboard(void) +void X11DRV_InitKeyboard( Display *display ) { - Display *display = thread_display(); KeySym *ksp; XModifierKeymap *mmp; KeySym keysym; @@ -1627,7 +1625,7 @@ void X11DRV_InitKeyboard(void) XFreeModifiermap(mmp); /* Detect the keyboard layout */ - X11DRV_KEYBOARD_DetectLayout(); + X11DRV_KEYBOARD_DetectLayout( display ); lkey = main_key_tab[kbd_layout].key; syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode; @@ -1975,7 +1973,7 @@ void X11DRV_MappingNotify( HWND dummy, XEvent *event ) wine_tsx11_lock(); XRefreshKeyboardMapping(&event->xmapping); wine_tsx11_unlock(); - X11DRV_InitKeyboard(); + X11DRV_InitKeyboard( thread_display() ); hwnd = GetFocus(); if (!hwnd) hwnd = GetActiveWindow(); diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 6df2713b582..3531918e022 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -476,14 +476,14 @@ LOAD_FUNCPTR(glXFreeMemoryNV) */ if(glxRequireVersion(3)) { - pglXChooseFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfig"); - pglXGetFBConfigAttrib = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttrib"); - pglXGetVisualFromFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfig"); - pglXQueryDrawable = (void*)pglXGetProcAddressARB((const GLubyte *) "glXQueryDrawable"); + pglXChooseFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfig"); + pglXGetFBConfigAttrib = pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttrib"); + pglXGetVisualFromFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfig"); + pglXQueryDrawable = pglXGetProcAddressARB((const GLubyte *) "glXQueryDrawable"); } else if(glxRequireExtension("GLX_SGIX_fbconfig")) { - pglXChooseFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfigSGIX"); - pglXGetFBConfigAttrib = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttribSGIX"); - pglXGetVisualFromFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfigSGIX"); + pglXChooseFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfigSGIX"); + pglXGetFBConfigAttrib = pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttribSGIX"); + pglXGetVisualFromFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfigSGIX"); /* The mesa libGL client library seems to forward glXQueryDrawable to the Xserver, so only * enable this function when the Xserver understand GLX 1.3 or newer @@ -491,10 +491,10 @@ LOAD_FUNCPTR(glXFreeMemoryNV) pglXQueryDrawable = NULL; } else if(strcmp("ATI", WineGLInfo.glxClientVendor) == 0) { TRACE("Overriding ATI GLX capabilities!\n"); - pglXChooseFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfig"); - pglXGetFBConfigAttrib = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttrib"); - pglXGetVisualFromFBConfig = (void*)pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfig"); - pglXQueryDrawable = (void*)pglXGetProcAddressARB((const GLubyte *) "glXQueryDrawable"); + pglXChooseFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXChooseFBConfig"); + pglXGetFBConfigAttrib = pglXGetProcAddressARB((const GLubyte *) "glXGetFBConfigAttrib"); + pglXGetVisualFromFBConfig = pglXGetProcAddressARB((const GLubyte *) "glXGetVisualFromFBConfig"); + pglXQueryDrawable = pglXGetProcAddressARB((const GLubyte *) "glXQueryDrawable"); /* Use client GLX information in case of the ATI drivers. We override the * capabilities over here and not somewhere else as ATI might better their @@ -507,13 +507,13 @@ LOAD_FUNCPTR(glXFreeMemoryNV) if(glxRequireExtension("GLX_ATI_render_texture")) { use_render_texture_ati = 1; - pglXBindTexImageATI = (void*)pglXGetProcAddressARB((const GLubyte *) "glXBindTexImageATI"); - pglXReleaseTexImageATI = (void*)pglXGetProcAddressARB((const GLubyte *) "glXReleaseTexImageATI"); - pglXDrawableAttribATI = (void*)pglXGetProcAddressARB((const GLubyte *) "glXDrawableAttribATI"); + pglXBindTexImageATI = pglXGetProcAddressARB((const GLubyte *) "glXBindTexImageATI"); + pglXReleaseTexImageATI = pglXGetProcAddressARB((const GLubyte *) "glXReleaseTexImageATI"); + pglXDrawableAttribATI = pglXGetProcAddressARB((const GLubyte *) "glXDrawableAttribATI"); } if(glxRequireExtension("GLX_MESA_copy_sub_buffer")) { - pglXCopySubBufferMESA = (void*)pglXGetProcAddressARB((const GLubyte *) "glXCopySubBufferMESA"); + pglXCopySubBufferMESA = pglXGetProcAddressARB((const GLubyte *) "glXCopySubBufferMESA"); } X11DRV_WineGL_LoadExtensions(); @@ -758,6 +758,7 @@ static int ConvertAttribWGLtoGLX(const int* iWGLAttr, int* oGLXAttr, Wine_GLPBuf nvfloatattrib = iWGLAttr[++cur]; TRACE("pAttr[%d] = WGL_FLOAT_COMPONENTS_NV: %x\n", cur, nvfloatattrib); break ; + case WGL_BIND_TO_TEXTURE_DEPTH_NV: case WGL_BIND_TO_TEXTURE_RGB_ARB: case WGL_BIND_TO_TEXTURE_RGBA_ARB: case WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV: @@ -1047,7 +1048,7 @@ int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev, if (TRACE_ON(opengl)) { TRACE("(%p,%p)\n", physDev, ppfd); - dump_PIXELFORMATDESCRIPTOR((const PIXELFORMATDESCRIPTOR *) ppfd); + dump_PIXELFORMATDESCRIPTOR(ppfd); } wine_tsx11_lock(); @@ -1692,7 +1693,7 @@ BOOL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) { if (!has_opengl()) { ERR("No libGL on this box - disabling OpenGL support !\n"); - return 0; + return FALSE; } wine_tsx11_lock(); @@ -1919,7 +1920,7 @@ static BOOL internal_wglUseFontBitmaps(HDC hdc, DWORD first, DWORD count, DWORD pglNewList(listBase++, GL_COMPILE); if (needed_size != 0) { pglBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY, - 0 - (int) gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - (int) gm.gmptGlyphOrigin.y, + 0 - gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - gm.gmptGlyphOrigin.y, gm.gmCellIncX, gm.gmCellIncY, gl_bitmap); } else { @@ -2320,7 +2321,7 @@ static HPBUFFERARB WINAPI X11DRV_wglCreatePbufferARB(HDC hdc, int iPixelFormat, create_failed: HeapFree(GetProcessHeap(), 0, object); TRACE("->(FAILED)\n"); - return (HPBUFFERARB) NULL; + return NULL; } /** diff --git a/dlls/winex11.drv/palette.c b/dlls/winex11.drv/palette.c index bb6d4939c34..1b74e2c7cc2 100644 --- a/dlls/winex11.drv/palette.c +++ b/dlls/winex11.drv/palette.c @@ -85,6 +85,15 @@ static unsigned char X11DRV_PALETTE_freeList[256]; static XContext palette_context; /* X context to associate a color mapping to a palette */ +static CRITICAL_SECTION palette_cs; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &palette_cs, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": palette_cs") } +}; +static CRITICAL_SECTION palette_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; + /**********************************************************************/ /* Map an EGA index (0..15) to a pixel value in the system color space. */ @@ -242,15 +251,15 @@ int X11DRV_PALETTE_Init(void) GetPaletteEntries( GetStockObject(DEFAULT_PALETTE), 0, NB_RESERVED_COLORS, sys_pal_template ); - if ((mapping = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(int) * NB_RESERVED_COLORS ))) - palette_set_mapping( GetStockObject(DEFAULT_PALETTE), mapping ); - if( X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL ) { palette_size = 0; } else { + if ((mapping = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(int) * NB_RESERVED_COLORS ))) + palette_set_mapping( GetStockObject(DEFAULT_PALETTE), mapping ); + if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE) X11DRV_PALETTE_BuildPrivateMap( sys_pal_template ); else @@ -761,13 +770,19 @@ BOOL X11DRV_IsSolidColor( COLORREF color ) if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_VIRTUAL) return TRUE; /* no palette */ + EnterCriticalSection( &palette_cs ); for (i = 0; i < palette_size ; i++, pEntry++) { if( i < COLOR_gapStart || i > COLOR_gapEnd ) if ((GetRValue(color) == pEntry->peRed) && (GetGValue(color) == pEntry->peGreen) && - (GetBValue(color) == pEntry->peBlue)) return TRUE; + (GetBValue(color) == pEntry->peBlue)) + { + LeaveCriticalSection( &palette_cs ); + return TRUE; + } } + LeaveCriticalSection( &palette_cs ); return FALSE; } @@ -810,8 +825,11 @@ COLORREF X11DRV_PALETTE_ToLogical(int pixel) if ((screen_depth <= 8) && (pixel < 256) && !(X11DRV_PALETTE_PaletteFlags & (X11DRV_PALETTE_VIRTUAL | X11DRV_PALETTE_FIXED)) ) { - return ( *(COLORREF*)(COLOR_sysPal + - ((X11DRV_PALETTE_XPixelToPalette)?X11DRV_PALETTE_XPixelToPalette[pixel]:pixel)) ) & 0x00ffffff; + COLORREF ret; + EnterCriticalSection( &palette_cs ); + ret = *(COLORREF *)(COLOR_sysPal + (X11DRV_PALETTE_XPixelToPalette ? X11DRV_PALETTE_XPixelToPalette[pixel]: pixel)) & 0x00ffffff; + LeaveCriticalSection( &palette_cs ); + return ret; } wine_tsx11_lock(); @@ -972,8 +990,10 @@ int X11DRV_PALETTE_ToPhysical( X11DRV_PDEVICE *physDev, COLORREF color ) ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? white : 1 - white; } + EnterCriticalSection( &palette_cs ); index = X11DRV_SysPaletteLookupPixel( color, FALSE); if (X11DRV_PALETTE_PaletteToXPixel) index = X11DRV_PALETTE_PaletteToXPixel[index]; + LeaveCriticalSection( &palette_cs ); /* TRACE(palette,"RGB(%lx) -> pixel %i\n", color, index); */ @@ -1096,11 +1116,6 @@ UINT X11DRV_RealizePalette( X11DRV_PDEVICE *physDev, HPALETTE hpal, BOOL primary if (!GetObjectW( hpal, sizeof(num_entries), &num_entries )) return 0; - /* reset dynamic system palette entries */ - - if( primary && X11DRV_PALETTE_firstFree != -1) - X11DRV_PALETTE_FormatSystemPalette(); - /* initialize palette mapping table */ prev_mapping = palette_get_mapping( hpal ); if (prev_mapping) @@ -1121,6 +1136,12 @@ UINT X11DRV_RealizePalette( X11DRV_PDEVICE *physDev, HPALETTE hpal, BOOL primary } if (!(num_entries = GetPaletteEntries( hpal, 0, num_entries, entries ))) return 0; + /* reset dynamic system palette entries */ + + EnterCriticalSection( &palette_cs ); + if( primary && X11DRV_PALETTE_firstFree != -1) + X11DRV_PALETTE_FormatSystemPalette(); + for (i = 0; i < num_entries; i++) { index = -1; @@ -1193,6 +1214,7 @@ UINT X11DRV_RealizePalette( X11DRV_PDEVICE *physDev, HPALETTE hpal, BOOL primary TRACE("entry %i (%x) -> pixel %i\n", i, *(COLORREF*)&entries[i], index); } + LeaveCriticalSection( &palette_cs ); return iRemapped; } @@ -1227,6 +1249,7 @@ UINT X11DRV_GetSystemPaletteEntries( X11DRV_PDEVICE *physDev, UINT start, UINT c if (start >= palette_size) return 0; if (start + count >= palette_size) count = palette_size - start; + EnterCriticalSection( &palette_cs ); for (i = 0; i < count; i++) { entries[i].peRed = COLOR_sysPal[start + i].peRed; @@ -1235,6 +1258,7 @@ UINT X11DRV_GetSystemPaletteEntries( X11DRV_PDEVICE *physDev, UINT start, UINT c entries[i].peFlags = 0; TRACE("\tidx(%02x) -> RGB(%08x)\n", start + i, *(COLORREF*)(entries + i) ); } + LeaveCriticalSection( &palette_cs ); return count; } @@ -1272,7 +1296,9 @@ COLORREF X11DRV_GetNearestColor( X11DRV_PDEVICE *physDev, COLORREF color ) color = RGB( entry.peRed, entry.peGreen, entry.peBlue ); } color &= 0x00ffffff; + EnterCriticalSection( &palette_cs ); nearest = (0x00ffffff & *(COLORREF*)(COLOR_sysPal + X11DRV_SysPaletteLookupPixel(color, FALSE))); + LeaveCriticalSection( &palette_cs ); TRACE("(%06x): returning %06x\n", color, nearest ); return nearest; @@ -1293,6 +1319,7 @@ UINT X11DRV_RealizeDefaultPalette( X11DRV_PDEVICE *physDev ) PALETTEENTRY entries[NB_RESERVED_COLORS]; GetPaletteEntries( GetStockObject(DEFAULT_PALETTE), 0, NB_RESERVED_COLORS, entries ); + EnterCriticalSection( &palette_cs ); for( i = 0; i < NB_RESERVED_COLORS; i++ ) { index = X11DRV_PALETTE_LookupSystemXPixel( RGB(entries[i].peRed, @@ -1305,6 +1332,7 @@ UINT X11DRV_RealizeDefaultPalette( X11DRV_PDEVICE *physDev ) ret++; } } + LeaveCriticalSection( &palette_cs ); } return ret; } diff --git a/dlls/winex11.drv/winpos.c b/dlls/winex11.drv/winpos.c index 1a3cde584a5..75906d3acf6 100644 --- a/dlls/winex11.drv/winpos.c +++ b/dlls/winex11.drv/winpos.c @@ -896,7 +896,7 @@ void X11DRV_resize_desktop( unsigned int width, unsigned int height ) SetWindowPos( hwnd, 0, virtual_screen_rect.left, virtual_screen_rect.top, virtual_screen_rect.right - virtual_screen_rect.left, virtual_screen_rect.bottom - virtual_screen_rect.top, - SWP_NOZORDER | SWP_NOACTIVATE ); + SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE ); SendMessageTimeoutW( HWND_BROADCAST, WM_DISPLAYCHANGE, screen_bpp, MAKELPARAM( width, height ), SMTO_ABORTIFHUNG, 2000, NULL ); } diff --git a/dlls/winex11.drv/wintab.c b/dlls/winex11.drv/wintab.c index d7bdb6aef5f..da18ce05e9d 100644 --- a/dlls/winex11.drv/wintab.c +++ b/dlls/winex11.drv/wintab.c @@ -436,6 +436,9 @@ static BOOL is_pad(const char *name, const char *type) } +/*********************************************************************** + * X11DRV_LoadTabletInfo (X11DRV.@) + */ void X11DRV_LoadTabletInfo(HWND hwnddefault) { const WCHAR SZ_CONTEXT_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','C','o','n','t','e','x','t',0}; @@ -602,7 +605,7 @@ void X11DRV_LoadTabletInfo(HWND hwnddefault) cursor->TYPE = CSR_TYPE_ERASER; - any = (XAnyClassPtr) (target->inputclassinfo); + any = target->inputclassinfo; for (class_loop = 0; class_loop < target->num_classes; class_loop++) { @@ -922,6 +925,9 @@ static void proximity_event( HWND hwnd, XEvent *event ) SendMessageW(hwndTabletDefault, WT_PROXIMITY, (event->type == proximity_in_type), (LPARAM)hwnd); } +/*********************************************************************** + * X11DRV_AttachEventQueueToTablet (X11DRV.@) + */ int X11DRV_AttachEventQueueToTablet(HWND hOwner) { struct x11drv_thread_data *data = x11drv_thread_data(); @@ -999,6 +1005,9 @@ int X11DRV_AttachEventQueueToTablet(HWND hOwner) return 0; } +/*********************************************************************** + * X11DRV_GetCurrentPacket (X11DRV.@) + */ int X11DRV_GetCurrentPacket(LPWTPACKET *packet) { memcpy(packet,&gMsgPacket,sizeof(WTPACKET)); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index ffd04699ba6..d7fb478d2fb 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -463,6 +463,8 @@ extern BOOL X11DRV_IsSolidColor(COLORREF color); extern COLORREF X11DRV_PALETTE_ToLogical(int pixel); extern int X11DRV_PALETTE_ToPhysical(X11DRV_PDEVICE *physDev, COLORREF color); +extern unsigned int depth_to_bpp( unsigned int depth ); + /* GDI escapes */ #define X11DRV_ESCAPE 6789 @@ -710,7 +712,7 @@ extern void X11DRV_ResetSelectionOwner(void); extern void X11DRV_SetFocus( HWND hwnd ); extern Cursor X11DRV_GetCursor( Display *display, struct tagCURSORICONINFO *ptr ); extern BOOL X11DRV_ClipCursor( LPCRECT clip ); -extern void X11DRV_InitKeyboard(void); +extern void X11DRV_InitKeyboard( Display *display ); extern void X11DRV_send_keyboard_input( WORD wVk, WORD wScan, DWORD dwFlags, DWORD time, DWORD dwExtraInfo, UINT injected_flags ); extern void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y, diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 8d822ef9dd5..444754b61af 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -278,6 +278,37 @@ void wine_tsx11_unlock(void) /*********************************************************************** + * depth_to_bpp + * + * Convert X11-reported depth to the BPP value that Windows apps expect to see. + */ +unsigned int depth_to_bpp( unsigned int depth ) +{ + switch (depth) + { + case 1: + case 8: + return depth; + case 15: + case 16: + return 16; + case 24: + /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run + * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference + * for windowing, but gl applications can get visuals with alpha channels. So we + * should check the framebuffer and/or opengl formats available to find out what the + * framebuffer actually does + */ + case 32: + return 32; + default: + FIXME( "Unexpected X11 depth %d bpp, what to report to app?\n", depth ); + return depth; + } +} + + +/*********************************************************************** * get_config_key * * Get a config key from either the app-specific or the default config @@ -491,35 +522,7 @@ static BOOL process_attach(void) screen_depth = desktop_vi->depth; XFree(desktop_vi); } - - switch(screen_depth) { - case 8: - screen_bpp = 8; - break; - - case 15: - /* In GetDeviceCaps MSDN description explicitly states that - * in 15 bpp mode 16 is returned. - */ - /* fall through */ - case 16: - screen_bpp = 16; - break; - - case 24: - /* This is not necessarily right. X11 always has 24 bits per pixel, but it can run - * with 24 bit framebuffers and 32 bit framebuffers. It doesn't make any difference - * for windowing, but gl applications can get visuals with alpha channels. So we - * should check the framebuffer and/or opengl formats available to find out what the - * framebuffer actually does - */ - screen_bpp = 32; - break; - - default: - FIXME("Unexpected X11 depth %d bpp, what to report to app?\n", screen_depth); - screen_bpp = screen_depth; - } + screen_bpp = depth_to_bpp( screen_depth ); XInternAtoms( display, (char **)atom_names, NB_XATOMS - FIRST_XATOM, False, X11DRV_Atoms ); @@ -540,7 +543,7 @@ static BOOL process_attach(void) X11DRV_XComposite_Init(); #endif - X11DRV_InitKeyboard(); + X11DRV_InitKeyboard( gdi_display ); X11DRV_InitClipboard(); return TRUE; diff --git a/dlls/winex11.drv/xfont.c b/dlls/winex11.drv/xfont.c index a55e77dc0bd..7dc3a400c01 100644 --- a/dlls/winex11.drv/xfont.c +++ b/dlls/winex11.drv/xfont.c @@ -3100,7 +3100,7 @@ static X_PHYSFONT XFONT_RealizeFont( LPLOGFONT16 plf, pfo->lpPixmap = NULL; for ( i = 0; i < X11FONT_REFOBJS_MAX; i++ ) - pfo->prefobjs[i] = (X_PHYSFONT)0xffffffff; /* invalid value */ + pfo->prefobjs[i] = 0xffffffff; /* invalid value */ /* special treatment for DBCS that needs multiple fonts */ /* All member of pfo must be set correctly. */ @@ -3165,7 +3165,7 @@ END: *faceMatched = pfo->fi->df.dfFace; *pcharsetMatched = pfo->fi->internal_charset; - return (X_PHYSFONT)(X_PFONT_MAGIC | index); + return X_PFONT_MAGIC | index; } /*********************************************************************** diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c index 782c779be27..ee735e61172 100644 --- a/dlls/winex11.drv/xinerama.c +++ b/dlls/winex11.drv/xinerama.c @@ -138,14 +138,15 @@ void xinerama_init( unsigned int width, unsigned int height ) { MONITORINFOEXW *primary; int i; + RECT rect; wine_tsx11_lock(); - SetRect( &virtual_screen_rect, 0, 0, width, height ); + SetRect( &rect, 0, 0, width, height ); if (root_window != DefaultRootWindow( gdi_display ) || !query_screens()) { - default_monitor.rcWork = default_monitor.rcMonitor = virtual_screen_rect; + default_monitor.rcWork = default_monitor.rcMonitor = rect; nb_monitors = 1; monitors = &default_monitor; } @@ -153,20 +154,21 @@ void xinerama_init( unsigned int width, unsigned int height ) primary = get_primary(); /* coordinates (0,0) have to point to the primary monitor origin */ - OffsetRect( &virtual_screen_rect, -primary->rcMonitor.left, -primary->rcMonitor.top ); + OffsetRect( &rect, -primary->rcMonitor.left, -primary->rcMonitor.top ); for (i = 0; i < nb_monitors; i++) { - OffsetRect( &monitors[i].rcMonitor, virtual_screen_rect.left, virtual_screen_rect.top ); - OffsetRect( &monitors[i].rcWork, virtual_screen_rect.left, virtual_screen_rect.top ); + OffsetRect( &monitors[i].rcMonitor, rect.left, rect.top ); + OffsetRect( &monitors[i].rcWork, rect.left, rect.top ); TRACE( "monitor %p: %s%s\n", index_to_monitor(i), wine_dbgstr_rect(&monitors[i].rcMonitor), (monitors[i].dwFlags & MONITORINFOF_PRIMARY) ? " (primary)" : "" ); } + virtual_screen_rect = rect; screen_width = primary->rcMonitor.right - primary->rcMonitor.left; screen_height = primary->rcMonitor.bottom - primary->rcMonitor.top; TRACE( "virtual size: %s primary size: %dx%d\n", - wine_dbgstr_rect(&virtual_screen_rect), screen_width, screen_height ); + wine_dbgstr_rect(&rect), screen_width, screen_height ); wine_tsx11_unlock(); ClipCursor( NULL ); /* reset the cursor clip rectangle */ diff --git a/dlls/wininet/ftp.c b/dlls/wininet/ftp.c index 44a5d33ef5e..f9ae2dbb213 100644 --- a/dlls/wininet/ftp.c +++ b/dlls/wininet/ftp.c @@ -474,7 +474,7 @@ lend: { INTERNET_ASYNC_RESULT iar; - iar.dwResult = (DWORD)bSuccess; + iar.dwResult = bSuccess; iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR; SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar, sizeof(INTERNET_ASYNC_RESULT)); @@ -1008,13 +1008,13 @@ lend: { INTERNET_ASYNC_RESULT iar; - iar.dwResult = (DWORD)bSuccess; + iar.dwResult = bSuccess; iar.dwError = bSuccess ? ERROR_SUCCESS : ERROR_INTERNET_EXTENDED_ERROR; SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar, sizeof(INTERNET_ASYNC_RESULT)); } - return (DWORD) bSuccess; + return bSuccess; } /*********************************************************************** diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index 16e1ec71c30..964140ed775 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -62,7 +62,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet); -static const WCHAR g_szHttp1_0[] = {' ','H','T','T','P','/','1','.','0',0 }; static const WCHAR g_szHttp1_1[] = {' ','H','T','T','P','/','1','.','1',0 }; static const WCHAR g_szReferer[] = {'R','e','f','e','r','e','r',0}; static const WCHAR g_szAccept[] = {'A','c','c','e','p','t',0}; @@ -257,7 +256,7 @@ static void HTTP_FixURL( LPWININETHTTPREQW lpwhr) } } -static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR verb, LPCWSTR path, BOOL http1_1 ) +static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR verb, LPCWSTR path ) { LPWSTR requestString; DWORD len, n; @@ -279,7 +278,7 @@ static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr, LPCWSTR ve req[n++] = verb; req[n++] = szSpace; req[n++] = path; - req[n++] = http1_1 ? g_szHttp1_1 : g_szHttp1_0; + req[n++] = g_szHttp1_1; /* Append custom request headers */ for (i = 0; i < lpwhr->nCustHeaders; i++) @@ -797,7 +796,7 @@ BOOL WINAPI HttpEndRequestA(HINTERNET hRequest, FIXME("Do we need to translate info out of these buffer?\n"); - HeapFree(GetProcessHeap(),0,(LPVOID)ptrW->lpvBuffer); + HeapFree(GetProcessHeap(),0,ptrW->lpvBuffer); ptrW2 = ptrW->Next; HeapFree(GetProcessHeap(),0,ptrW); ptrW = ptrW2; @@ -1187,9 +1186,11 @@ static UINT HTTP_DecodeBase64( LPCWSTR base64, LPSTR bin ) * * Insert or delete the authorization field in the request header. */ -static BOOL HTTP_InsertAuthorizationForHeader( LPWININETHTTPREQW lpwhr, struct HttpAuthInfo *pAuthInfo, LPCWSTR header ) +static BOOL HTTP_InsertAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR header, BOOL first ) { WCHAR *authorization = NULL; + struct HttpAuthInfo *pAuthInfo = lpwhr->pAuthInfo; + DWORD flags; if (pAuthInfo && pAuthInfo->auth_data_len) { @@ -1222,35 +1223,17 @@ static BOOL HTTP_InsertAuthorizationForHeader( LPWININETHTTPREQW lpwhr, struct H TRACE("Inserting authorization: %s\n", debugstr_w(authorization)); - HTTP_ProcessHeader(lpwhr, header, authorization, - HTTP_ADDHDR_FLAG_REPLACE | HTTP_ADDHDR_FLAG_REQ); + /* make sure not to overwrite any caller supplied authorization header */ + flags = HTTP_ADDHDR_FLAG_REQ; + flags |= first ? HTTP_ADDHDR_FLAG_ADD_IF_NEW : HTTP_ADDHDR_FLAG_REPLACE; - HeapFree(GetProcessHeap(), 0, authorization); + HTTP_ProcessHeader(lpwhr, header, authorization, flags); + HeapFree(GetProcessHeap(), 0, authorization); return TRUE; } /*********************************************************************** - * HTTP_InsertAuthorization - * - * Insert the authorization field in the request header - */ -static BOOL HTTP_InsertAuthorization( LPWININETHTTPREQW lpwhr ) -{ - return HTTP_InsertAuthorizationForHeader(lpwhr, lpwhr->pAuthInfo, szAuthorization); -} - -/*********************************************************************** - * HTTP_InsertProxyAuthorization - * - * Insert the proxy authorization field in the request header - */ -static BOOL HTTP_InsertProxyAuthorization( LPWININETHTTPREQW lpwhr ) -{ - return HTTP_InsertAuthorizationForHeader(lpwhr, lpwhr->pProxyAuthInfo, szProxy_Authorization); -} - -/*********************************************************************** * HTTP_DealWithProxy */ static BOOL HTTP_DealWithProxy( LPWININETAPPINFOW hIC, @@ -1666,7 +1649,7 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLev BOOL ret; if (request_only) - headers = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath, FALSE); + headers = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath); else headers = lpwhr->lpszRawHeaders; @@ -2536,7 +2519,7 @@ static BOOL HTTP_SecureProxyConnect(LPWININETHTTPREQW lpwhr) lpszPath = HeapAlloc( GetProcessHeap(), 0, (lstrlenW( lpwhs->lpszHostName ) + 13)*sizeof(WCHAR) ); sprintfW( lpszPath, szFormat, lpwhs->lpszHostName, lpwhs->nHostPort ); - requestString = HTTP_BuildHeaderRequestString( lpwhr, szConnect, lpszPath, FALSE ); + requestString = HTTP_BuildHeaderRequestString( lpwhr, szConnect, lpszPath ); HeapFree( GetProcessHeap(), 0, lpszPath ); len = WideCharToMultiByte( CP_ACP, 0, requestString, -1, @@ -2582,6 +2565,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, BOOL loop_next; INTERNET_ASYNC_RESULT iar; static const WCHAR szClose[] = { 'C','l','o','s','e',0 }; + static const WCHAR szPost[] = { 'P','O','S','T',0 }; static const WCHAR szContentLength[] = { 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','l','i','\r','\n',0 }; WCHAR contentLengthStr[sizeof szContentLength/2 /* includes \r\n */ + 20 /* int */ ]; @@ -2594,9 +2578,11 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, INTERNET_SetLastError(0); HTTP_FixVerb(lpwhr); - - sprintfW(contentLengthStr, szContentLength, dwContentLength); - HTTP_HttpAddRequestHeadersW(lpwhr, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REPLACE); + if (dwContentLength || !strcmpW(lpwhr->lpszVerb, szPost)) + { + sprintfW(contentLengthStr, szContentLength, dwContentLength); + HTTP_HttpAddRequestHeadersW(lpwhr, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REPLACE); + } do { @@ -2621,8 +2607,8 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, lpwhr->hdr.dwFlags & INTERNET_FLAG_KEEP_CONNECTION ? szKeepAlive : szClose, HTTP_ADDHDR_FLAG_REQ | HTTP_ADDHDR_FLAG_REPLACE); - HTTP_InsertAuthorization(lpwhr); - HTTP_InsertProxyAuthorization(lpwhr); + HTTP_InsertAuthorization(lpwhr, szAuthorization, !loop_next); + HTTP_InsertAuthorization(lpwhr, szProxy_Authorization, !loop_next); /* add the headers the caller supplied */ if( lpszHeaders && dwHeaderLength ) @@ -2631,7 +2617,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REPLACE); } - requestString = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath, FALSE); + requestString = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath); TRACE("Request header -> %s\n", debugstr_w(requestString) ); @@ -2795,6 +2781,12 @@ HINTERNET HTTP_Connect(LPWININETAPPINFOW hIC, LPCWSTR lpszServerName, TRACE("-->\n"); + if (!lpszServerName || !lpszServerName[0]) + { + INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + goto lerror; + } + assert( hIC->hdr.htype == WH_HINIT ); lpwhs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WININETHTTPSESSIONW)); diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index 2c3e9a9ad0e..595a718f9f6 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -265,7 +265,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) URLCacheContainers_CreateDefaults(); - WININET_hModule = (HMODULE)hinstDLL; + WININET_hModule = hinstDLL; case DLL_THREAD_ATTACH: break; @@ -568,7 +568,7 @@ lend: HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType, LPCSTR lpszProxy, LPCSTR lpszProxyBypass, DWORD dwFlags) { - HINTERNET rc = (HINTERNET)NULL; + HINTERNET rc = NULL; INT len; WCHAR *szAgent = NULL, *szProxy = NULL, *szBypass = NULL; @@ -851,7 +851,7 @@ HINTERNET WINAPI InternetConnectA(HINTERNET hInternet, LPCSTR lpszUserName, LPCSTR lpszPassword, DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext) { - HINTERNET rc = (HINTERNET)NULL; + HINTERNET rc = NULL; INT len = 0; LPWSTR szServerName = NULL; LPWSTR szUserName = NULL; @@ -1700,7 +1700,7 @@ BOOL WINAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer , LPWININETHANDLEHEADER lpwh; TRACE("\n"); - lpwh = (LPWININETHANDLEHEADER) WININET_GetObject( hFile ); + lpwh = WININET_GetObject( hFile ); if (NULL == lpwh) return FALSE; @@ -2544,7 +2544,7 @@ BOOL WINAPI InternetSetOptionA(HINTERNET hInternet, DWORD dwOption, LPWININETHANDLEHEADER lpwh; INTERNET_STATUS_CALLBACK callback = *(INTERNET_STATUS_CALLBACK *)lpBuffer; - if (!(lpwh = (LPWININETHANDLEHEADER)WININET_GetObject(hInternet))) return FALSE; + if (!(lpwh = WININET_GetObject(hInternet))) return FALSE; r = (set_status_callback(lpwh, callback, FALSE) != INTERNET_INVALID_STATUS_CALLBACK); WININET_Release(lpwh); return r; @@ -3104,7 +3104,7 @@ HINTERNET WINAPI InternetOpenUrlW(HINTERNET hInternet, LPCWSTR lpszUrl, HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext) { - HINTERNET rc = (HINTERNET)NULL; + HINTERNET rc = NULL; INT lenUrl; INT lenHeaders = 0; @@ -3117,16 +3117,16 @@ HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, lenUrl = MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, NULL, 0 ); szUrl = HeapAlloc(GetProcessHeap(), 0, lenUrl*sizeof(WCHAR)); if(!szUrl) - return (HINTERNET)NULL; + return NULL; MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, szUrl, lenUrl); } - + if(lpszHeaders) { lenHeaders = MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, NULL, 0 ); szHeaders = HeapAlloc(GetProcessHeap(), 0, lenHeaders*sizeof(WCHAR)); if(!szHeaders) { HeapFree(GetProcessHeap(), 0, szUrl); - return (HINTERNET)NULL; + return NULL; } MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, szHeaders, lenHeaders); } diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c index 457a65ffd97..f48f61f511b 100644 --- a/dlls/wininet/tests/http.c +++ b/dlls/wininet/tests/http.c @@ -929,9 +929,19 @@ static void InternetOpenRequest_test(void) session = InternetOpenA("Wine Regression Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); ok(session != NULL ,"Unable to open Internet session\n"); + connect = InternetConnectA(session, NULL, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, + INTERNET_SERVICE_HTTP, 0, 0); + ok(connect == NULL, "InternetConnectA should have failed\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "InternetConnectA with NULL server named should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError()); + + connect = InternetConnectA(session, "", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, + INTERNET_SERVICE_HTTP, 0, 0); + ok(connect == NULL, "InternetConnectA should have failed\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "InternetConnectA with blank server named should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError()); + connect = InternetConnectA(session, "winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); - ok(connect != NULL, "Unable to connect to http://winehq.org\n"); + ok(connect != NULL, "Unable to connect to http://winehq.org with error %d\n", GetLastError()); request = HttpOpenRequestA(connect, NULL, "/", NULL, NULL, types, INTERNET_FLAG_NO_CACHE_WRITE, 0); if (!request && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED) @@ -1275,8 +1285,13 @@ static DWORD CALLBACK server_thread(LPVOID param) if (strstr(buffer, "GET /test1")) { - send(c, okmsg, sizeof okmsg-1, 0); - send(c, page1, sizeof page1-1, 0); + if (!strstr(buffer, "Content-Length: 0")) + { + send(c, okmsg, sizeof okmsg-1, 0); + send(c, page1, sizeof page1-1, 0); + } + else + send(c, notokmsg, sizeof notokmsg-1, 0); } if (strstr(buffer, "/test2")) @@ -1306,7 +1321,7 @@ static DWORD CALLBACK server_thread(LPVOID param) send(c, notokmsg, sizeof notokmsg-1, 0); } - if (strstr(buffer, "/test5")) + if (strstr(buffer, "POST /test5")) { if (strstr(buffer, "Content-Length: 0")) { @@ -1317,7 +1332,7 @@ static DWORD CALLBACK server_thread(LPVOID param) send(c, notokmsg, sizeof notokmsg-1, 0); } - if (strstr(buffer, "/quit")) + if (strstr(buffer, "GET /quit")) { send(c, okmsg, sizeof okmsg-1, 0); send(c, page1, sizeof page1-1, 0); @@ -1333,7 +1348,7 @@ static DWORD CALLBACK server_thread(LPVOID param) return 0; } -static void test_basic_request(int port, const char *url) +static void test_basic_request(int port, const char *verb, const char *url) { HINTERNET hi, hc, hr; DWORD r, count; @@ -1345,7 +1360,7 @@ static void test_basic_request(int port, const char *url) hc = InternetConnect(hi, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); ok(hc != NULL, "connect failed\n"); - hr = HttpOpenRequest(hc, NULL, url, NULL, NULL, NULL, 0, 0); + hr = HttpOpenRequest(hc, verb, url, NULL, NULL, NULL, 0, 0); ok(hr != NULL, "HttpOpenRequest failed\n"); r = HttpSendRequest(hr, NULL, 0, NULL, 0); @@ -1492,7 +1507,10 @@ static void test_header_handling_order(int port) request = HttpOpenRequest(connect, NULL, "/test3", NULL, NULL, types, INTERNET_FLAG_KEEP_CONNECTION, 0); ok(request != NULL, "HttpOpenRequest failed\n"); - ret = HttpSendRequest(request, authorization, ~0UL, NULL, 0); + ret = HttpAddRequestHeaders(request, authorization, ~0UL, HTTP_ADDREQ_FLAG_ADD); + ok(ret, "HttpAddRequestHeaders failed\n"); + + ret = HttpSendRequest(request, NULL, 0, NULL, 0); ok(ret, "HttpSendRequest failed\n"); status = 0; @@ -1537,14 +1555,14 @@ static void test_http_connection(void) if (r != WAIT_OBJECT_0) return; - test_basic_request(si.port, "/test1"); + test_basic_request(si.port, "GET", "/test1"); test_proxy_indirect(si.port); test_proxy_direct(si.port); test_header_handling_order(si.port); - test_basic_request(si.port, "/test5"); + test_basic_request(si.port, "POST", "/test5"); /* send the basic request again to shutdown the server thread */ - test_basic_request(si.port, "/quit"); + test_basic_request(si.port, "GET", "/quit"); r = WaitForSingleObject(hThread, 3000); ok( r == WAIT_OBJECT_0, "thread wait failed\n"); diff --git a/dlls/wininet/urlcache.c b/dlls/wininet/urlcache.c index 7dfb20aec10..dc92affa6d1 100644 --- a/dlls/wininet/urlcache.c +++ b/dlls/wininet/urlcache.c @@ -1125,7 +1125,7 @@ static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct HASH_CACHEFILE_ENTRY * pHashEntry; DWORD dwHashTableNumber = 0; - key = (DWORD)(key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; + key = (key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; for (pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable); ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) >= ENTRY_START_OFFSET) && ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) < pHeader->dwFileSize); @@ -1147,7 +1147,7 @@ static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct for (i = 0; i < HASHTABLE_BLOCKSIZE; i++) { struct _HASH_ENTRY * pHashElement = &pHashEntry->HashTable[offset + i]; - if (key == (DWORD)(pHashElement->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES) + if (key == (pHashElement->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES) { /* FIXME: we should make sure that this is the right element * before returning and claiming that it is. We can do this @@ -1195,7 +1195,7 @@ static BOOL URLCache_FindHashW(LPCURLCACHE_HEADER pHeader, LPCWSTR lpszUrl, stru */ static BOOL URLCache_HashEntrySetUse(struct _HASH_ENTRY * pHashEntry, DWORD dwUseCount) { - pHashEntry->dwHashKey = dwUseCount | (DWORD)(pHashEntry->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; + pHashEntry->dwHashKey = dwUseCount | (pHashEntry->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; return TRUE; } @@ -1238,7 +1238,7 @@ static BOOL URLCache_AddEntryToHash(LPURLCACHE_HEADER pHeader, LPCSTR lpszUrl, D HASH_CACHEFILE_ENTRY * pHashEntry; DWORD dwHashTableNumber = 0; - key = (DWORD)(key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; + key = (key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES; for (pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable); ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) >= ENTRY_START_OFFSET) && ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) < pHeader->dwFileSize); diff --git a/dlls/wininet/utility.c b/dlls/wininet/utility.c index 97b4be5ffa9..352b2609c17 100644 --- a/dlls/wininet/utility.c +++ b/dlls/wininet/utility.c @@ -162,7 +162,7 @@ BOOL GetAddress(LPCWSTR lpszServerName, INTERNET_PORT nServerPort, memset(psa,0,sizeof(struct sockaddr_in)); memcpy((char *)&psa->sin_addr, phe->h_addr, phe->h_length); psa->sin_family = phe->h_addrtype; - psa->sin_port = htons((u_short)nServerPort); + psa->sin_port = htons(nServerPort); return TRUE; } diff --git a/dlls/winmm/message16.c b/dlls/winmm/message16.c index c9d5f95dcfb..77a9076cd31 100644 --- a/dlls/winmm/message16.c +++ b/dlls/winmm/message16.c @@ -323,7 +323,7 @@ static WINMM_MapType MMDRV_MidiOut_Map16To32W (UINT wMsg, LPDWORD lpdwUser, DW mh32->dwFlags = mh16->dwFlags; /* FIXME: nothing on mh32->lpNext */ /* could link the mh32->lpNext at this level for memory house keeping */ - mh32->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? ((LPMIDIHDR)mh16)->dwOffset : 0; + mh32->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? mh16->dwOffset : 0; mh16->lpNext = mh32; /* for reuse in unprepare and write */ /* store size of passed MIDIHDR?? structure to know if dwOffset is available or not */ mh16->reserved = *lpParam2; @@ -340,7 +340,7 @@ static WINMM_MapType MMDRV_MidiOut_Map16To32W (UINT wMsg, LPDWORD lpdwUser, DW case MODM_LONGDATA: { LPMIDIHDR mh16 = MapSL(*lpParam1); - LPMIDIHDR mh32 = (LPMIDIHDR)mh16->lpNext; + LPMIDIHDR mh32 = mh16->lpNext; *lpParam1 = (DWORD)mh32; *lpParam2 = sizeof(MIDIHDR); @@ -486,7 +486,7 @@ static WINMM_MapType MMDRV_MidiOut_Map32WTo16 (UINT wMsg, LPDWORD lpdwUser, DW /* could link the mh32->lpNext at this level for memory house keeping */ mh16->dwOffset = (*lpParam2 >= sizeof(MIDIHDR)) ? mh32->dwOffset : 0; - mh32->lpNext = (LPMIDIHDR)mh16; /* for reuse in unprepare and write */ + mh32->lpNext = mh16; /* for reuse in unprepare and write */ mh32->reserved = *lpParam2; TRACE("mh16=%08lx mh16->lpData=%p mh32->buflen=%u mh32->lpData=%p\n", @@ -503,7 +503,7 @@ static WINMM_MapType MMDRV_MidiOut_Map32WTo16 (UINT wMsg, LPDWORD lpdwUser, DW case MODM_LONGDATA: { LPMIDIHDR mh32 = (LPMIDIHDR)(*lpParam1); - LPMIDIHDR mh16 = (LPMIDIHDR)mh32->lpNext; + LPMIDIHDR mh16 = mh32->lpNext; LPSTR ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR); assert(*(LPMIDIHDR*)ptr == mh32); @@ -618,7 +618,7 @@ static WINMM_MapType MMDRV_MidiOut_UnMap32WTo16(UINT wMsg, LPDWORD lpdwUser, DW LPSTR ptr = (LPSTR)mh16 - sizeof(LPMIDIHDR); LPMIDIHDR mh32 = *(LPMIDIHDR*)ptr; - assert(mh32->lpNext == (LPMIDIHDR)mh16); + assert(mh32->lpNext == mh16); UnMapLS( *lpParam1 ); mh32->dwBytesRecorded = mh16->dwBytesRecorded; mh32->dwUser = mh16->dwUser; @@ -784,7 +784,7 @@ static WINMM_MapType MMDRV_WaveIn_Map16To32W (UINT wMsg, LPDWORD lpdwUser, DWO case WIDM_UNPREPARE: { LPWAVEHDR wh16 = MapSL(*lpParam1); - LPWAVEHDR wh32 = (LPWAVEHDR)wh16->lpNext; + LPWAVEHDR wh32 = wh16->lpNext; *lpParam1 = (DWORD)wh32; *lpParam2 = sizeof(WAVEHDR); @@ -914,8 +914,8 @@ static WINMM_MapType MMDRV_WaveIn_Map32WTo16 (UINT wMsg, LPDWORD lpdwUser, DWO xxx extra bytes to WAVEFORMATEX */ if (wod32->lpFormat->wFormatTag != WAVE_FORMAT_PCM) { - TRACE("Allocating %u extra bytes (%d)\n", ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize, wod32->lpFormat->wFormatTag); - sz += ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize; + TRACE("Allocating %u extra bytes (%d)\n", wod32->lpFormat->cbSize, wod32->lpFormat->wFormatTag); + sz += wod32->lpFormat->cbSize; } ptr = HeapAlloc( GetProcessHeap(), 0, @@ -1283,7 +1283,7 @@ static WINMM_MapType MMDRV_WaveOut_Map16To32W (UINT wMsg, LPDWORD lpdwUser, DW case WODM_WRITE: { LPWAVEHDR wh16 = MapSL(*lpParam1); - LPWAVEHDR wh32 = (LPWAVEHDR)wh16->lpNext; + LPWAVEHDR wh32 = wh16->lpNext; *lpParam1 = (DWORD)wh32; *lpParam2 = sizeof(WAVEHDR); @@ -1473,8 +1473,8 @@ static WINMM_MapType MMDRV_WaveOut_Map32WTo16 (UINT wMsg, LPDWORD lpdwUser, DW xxx extra bytes to WAVEFORMATEX */ if (wod32->lpFormat->wFormatTag != WAVE_FORMAT_PCM) { - TRACE("Allocating %u extra bytes (%d)\n", ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize, wod32->lpFormat->wFormatTag); - sz += ((LPWAVEFORMATEX)wod32->lpFormat)->cbSize; + TRACE("Allocating %u extra bytes (%d)\n", wod32->lpFormat->cbSize, wod32->lpFormat->wFormatTag); + sz += wod32->lpFormat->cbSize; } ptr = HeapAlloc( GetProcessHeap(), 0, @@ -3348,7 +3348,7 @@ static WINMM_MapType MCI_UnMapMsg32WTo16(WORD uDevType, WORD wMsg, DWORD dwFlag mip32w->lpstrReturn, mip32w->dwRetSize / sizeof(WCHAR)); UnMapLS( lParam ); UnMapLS( mip16->lpstrReturn ); - HeapFree( GetProcessHeap(), 0, (void*)MapSL(mip16->lpstrReturn) ); + HeapFree( GetProcessHeap(), 0, MapSL(mip16->lpstrReturn) ); HeapFree( GetProcessHeap(), 0, (char*)mip16 - sizeof(LPMCI_OPEN_PARMSW) ); } return WINMM_MAP_OK; diff --git a/dlls/winmm/winmm.c b/dlls/winmm/winmm.c index 4ecf34b9b02..7e1138d34f8 100644 --- a/dlls/winmm/winmm.c +++ b/dlls/winmm/winmm.c @@ -1508,7 +1508,7 @@ static BOOL MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream* lpMidiStrm, LPWI /* this is not quite what MS doc says... */ midiOutReset(lpMidiStrm->hDevice); /* empty list of already submitted buffers */ - for (lpMidiHdr = lpMidiStrm->lpMidiHdr; lpMidiHdr; lpMidiHdr = (LPMIDIHDR)lpMidiHdr->lpNext) { + for (lpMidiHdr = lpMidiStrm->lpMidiHdr; lpMidiHdr; lpMidiHdr = lpMidiHdr->lpNext) { lpMidiHdr->dwFlags |= MHDR_DONE; lpMidiHdr->dwFlags &= ~MHDR_INQUEUE; @@ -1592,7 +1592,7 @@ static BOOL MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream* lpMidiStrm, LPWI break; } - for (lpmh = &lpMidiStrm->lpMidiHdr; *lpmh; lpmh = (LPMIDIHDR*)&((*lpmh)->lpNext)); + for (lpmh = &lpMidiStrm->lpMidiHdr; *lpmh; lpmh = &(*lpmh)->lpNext); *lpmh = lpMidiHdr; lpMidiHdr = (LPMIDIHDR)msg->lParam; lpMidiHdr->lpNext = 0; @@ -1720,7 +1720,7 @@ static DWORD CALLBACK MMSYSTEM_MidiStream_Player(LPVOID pmt) lpMidiHdr->dwFlags |= MHDR_DONE; lpMidiHdr->dwFlags &= ~MHDR_INQUEUE; - lpMidiStrm->lpMidiHdr = (LPMIDIHDR)lpMidiHdr->lpNext; + lpMidiStrm->lpMidiHdr = lpMidiHdr->lpNext; DriverCallback(lpwm->mod.dwCallback, lpMidiStrm->wFlags, (HDRVR)lpMidiStrm->hDevice, MM_MOM_DONE, lpwm->mod.dwInstance, (DWORD)lpMidiHdr, 0L); diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c index 3143429d554..4ba9f28f403 100644 --- a/dlls/winspool.drv/info.c +++ b/dlls/winspool.drv/info.c @@ -86,14 +86,6 @@ static CRITICAL_SECTION printer_handles_cs = { &printer_handles_cs_debug, -1, 0, /* ############################### */ typedef struct { - WCHAR src[MAX_PATH+MAX_PATH]; - WCHAR dst[MAX_PATH+MAX_PATH]; - DWORD srclen; - DWORD dstlen; - DWORD copyflags; -} apd_data_t; - -typedef struct { struct list entry; LPWSTR name; LPWSTR dllname; @@ -353,67 +345,11 @@ static LPSTR strdupWtoA( LPCWSTR str ) } /****************************************************************** - * apd_copyfile [internal] - * - * Copy a file from the driverdirectory to the versioned directory - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL apd_copyfile(LPWSTR filename, apd_data_t *apd) -{ - LPWSTR ptr; - LPWSTR srcname; - DWORD res; - - apd->src[apd->srclen] = '\0'; - apd->dst[apd->dstlen] = '\0'; - - if (!filename || !filename[0]) { - /* nothing to copy */ - return TRUE; - } - - ptr = strrchrW(filename, '\\'); - if (ptr) { - ptr++; - } - else - { - ptr = filename; - } - - if (apd->copyflags & APD_COPY_FROM_DIRECTORY) { - /* we have an absolute Path */ - srcname = filename; - } - else - { - srcname = apd->src; - lstrcatW(srcname, ptr); - } - lstrcatW(apd->dst, ptr); - - TRACE("%s => %s\n", debugstr_w(filename), debugstr_w(apd->dst)); - - /* FIXME: handle APD_COPY_NEW_FILES */ - res = CopyFileW(srcname, apd->dst, FALSE); - TRACE("got %u with %u\n", res, GetLastError()); - - /* FIXME: install of wineps.drv must be fixed, before we return the real result - return res; - */ - return TRUE; -} - - -/****************************************************************** * Return the number of bytes for an multi_sz string. * The result includes all \0s * (specifically the extra \0, that is needed as multi_sz terminator). */ +#if 0 static int multi_sz_lenW(const WCHAR *str) { const WCHAR *ptr = str; @@ -425,7 +361,7 @@ static int multi_sz_lenW(const WCHAR *str) return (ptr - str + 1) * sizeof(WCHAR); } - +#endif /* ################################ */ static int multi_sz_lenA(const char *str) @@ -4844,57 +4780,25 @@ BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded) { - DWORD needed; - const printenv_t * env; - TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName), debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded); - if(pName != NULL && pName[0]) { - FIXME("pName unsupported: %s\n", debugstr_w(pName)); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - env = validate_envW(pEnvironment); - if(!env) return FALSE; /* pEnvironment invalid or unsupported */ + if ((backend == NULL) && !load_backend()) return FALSE; - if(Level != 1) { - WARN("(Level: %d) is ignored in win9x\n", Level); + if (Level != 1) { + /* (Level != 1) is ignored in win9x */ SetLastError(ERROR_INVALID_LEVEL); return FALSE; } - - /* GetSystemDirectoryW returns number of WCHAR including the '\0' */ - needed = GetSystemDirectoryW(NULL, 0); - /* add the Size for the Subdirectories */ - needed += lstrlenW(spooldriversW); - needed += lstrlenW(env->subdir); - needed *= sizeof(WCHAR); /* return-value is size in Bytes */ - - if(pcbNeeded) - *pcbNeeded = needed; - TRACE("required: 0x%x/%d\n", needed, needed); - if(needed > cbBuf) { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - if(pcbNeeded == NULL) { - WARN("(pcbNeeded == NULL) is ignored in win9x\n"); + if (pcbNeeded == NULL) { + /* (pcbNeeded == NULL) is ignored in win9x */ SetLastError(RPC_X_NULL_REF_POINTER); return FALSE; } - if(pDriverDirectory == NULL) { - /* ERROR_INVALID_USER_BUFFER is NT, ERROR_INVALID_PARAMETER is win9x */ - SetLastError(ERROR_INVALID_USER_BUFFER); - return FALSE; - } - - GetSystemDirectoryW((LPWSTR) pDriverDirectory, cbBuf/sizeof(WCHAR)); - /* add the Subdirectories */ - lstrcatW((LPWSTR) pDriverDirectory, spooldriversW); - lstrcatW((LPWSTR) pDriverDirectory, env->subdir); - TRACE(" => %s\n", debugstr_w((LPWSTR) pDriverDirectory)); - return TRUE; + + return backend->fpGetPrinterDriverDirectory(pName, pEnvironment, Level, + pDriverDirectory, cbBuf, pcbNeeded); + } @@ -6428,18 +6332,10 @@ BOOL WINAPI AddPrinterConnectionW( LPWSTR pName ) */ BOOL WINAPI AddPrinterDriverExW( LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags) { - const printenv_t *env; - apd_data_t apd; - DRIVER_INFO_8W di; - LPWSTR ptr; - HKEY hroot; - HKEY hdrv; - DWORD disposition; - DWORD len; - LONG lres; - TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags); + if ((backend == NULL) && !load_backend()) return FALSE; + if (level < 2 || level == 5 || level == 7 || level > 8) { SetLastError(ERROR_INVALID_LEVEL); return FALSE; @@ -6450,141 +6346,7 @@ BOOL WINAPI AddPrinterDriverExW( LPWSTR pName, DWORD level, LPBYTE pDriverInfo, return FALSE; } - if ((dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY) != APD_COPY_ALL_FILES) { - FIXME("Flags 0x%x ignored (Fallback to APD_COPY_ALL_FILES)\n", dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY); - } - - ptr = get_servername_from_name(pName); - HeapFree(GetProcessHeap(), 0, ptr); - if (ptr) { - FIXME("not supported for server: %s\n", debugstr_w(pName)); - SetLastError(ERROR_ACCESS_DENIED); - return FALSE; - } - - /* we need to set all entries in the Registry, independent from the Level of - DRIVER_INFO, that the caller supplied */ - - ZeroMemory(&di, sizeof(di)); - if (pDriverInfo && (level < (sizeof(di_sizeof) / sizeof(di_sizeof[0])))) { - memcpy(&di, pDriverInfo, di_sizeof[level]); - } - - /* dump the most used infos */ - TRACE("%p: .cVersion : 0x%x/%d\n", pDriverInfo, di.cVersion, di.cVersion); - TRACE("%p: .pName : %s\n", di.pName, debugstr_w(di.pName)); - TRACE("%p: .pEnvironment: %s\n", di.pEnvironment, debugstr_w(di.pEnvironment)); - TRACE("%p: .pDriverPath : %s\n", di.pDriverPath, debugstr_w(di.pDriverPath)); - TRACE("%p: .pDataFile : %s\n", di.pDataFile, debugstr_w(di.pDataFile)); - TRACE("%p: .pConfigFile : %s\n", di.pConfigFile, debugstr_w(di.pConfigFile)); - TRACE("%p: .pHelpFile : %s\n", di.pHelpFile, debugstr_w(di.pHelpFile)); - /* dump only the first of the additional Files */ - TRACE("%p: .pDependentFiles: %s\n", di.pDependentFiles, debugstr_w(di.pDependentFiles)); - - - /* check environment */ - env = validate_envW(di.pEnvironment); - if (env == NULL) return FALSE; /* ERROR_INVALID_ENVIRONMENT */ - - /* fill the copy-data / get the driverdir */ - len = sizeof(apd.src) - sizeof(Version3_SubdirW) - sizeof(WCHAR); - if (!GetPrinterDriverDirectoryW(NULL, (LPWSTR) env->envname, 1, - (LPBYTE) apd.src, len, &len)) { - /* Should never Fail */ - return FALSE; - } - memcpy(apd.dst, apd.src, len); - lstrcatW(apd.src, backslashW); - apd.srclen = lstrlenW(apd.src); - lstrcatW(apd.dst, env->versionsubdir); - lstrcatW(apd.dst, backslashW); - apd.dstlen = lstrlenW(apd.dst); - apd.copyflags = dwFileCopyFlags; - CreateDirectoryW(apd.src, NULL); - CreateDirectoryW(apd.dst, NULL); - - /* Fill the Registry for the Driver */ - hroot = WINSPOOL_OpenDriverReg(env->envname, TRUE); - if(!hroot) { - ERR("Can't create Drivers key\n"); - return FALSE; - } - - if ((lres = RegCreateKeyExW(hroot, di.pName, 0, NULL, REG_OPTION_NON_VOLATILE, - KEY_WRITE | KEY_QUERY_VALUE, NULL, - &hdrv, &disposition)) != ERROR_SUCCESS) { - - ERR("can't create driver %s: %u\n", debugstr_w(di.pName), lres); - RegCloseKey(hroot); - SetLastError(lres); - return FALSE; - } - RegCloseKey(hroot); - - if (disposition == REG_OPENED_EXISTING_KEY) { - TRACE("driver %s already installed\n", debugstr_w(di.pName)); - RegCloseKey(hdrv); - SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED); - return FALSE; - } - - /* Verified with the Adobe PS Driver, that w2k does not use di.Version */ - RegSetValueExW(hdrv, VersionW, 0, REG_DWORD, (LPBYTE) &env->driverversion, - sizeof(DWORD)); - - RegSetValueExW(hdrv, DriverW, 0, REG_SZ, (LPBYTE) di.pDriverPath, - (lstrlenW(di.pDriverPath)+1)* sizeof(WCHAR)); - apd_copyfile(di.pDriverPath, &apd); - - RegSetValueExW(hdrv, Data_FileW, 0, REG_SZ, (LPBYTE) di.pDataFile, - (lstrlenW(di.pDataFile)+1)* sizeof(WCHAR)); - apd_copyfile(di.pDataFile, &apd); - - RegSetValueExW(hdrv, Configuration_FileW, 0, REG_SZ, (LPBYTE) di.pConfigFile, - (lstrlenW(di.pConfigFile)+1)* sizeof(WCHAR)); - apd_copyfile(di.pConfigFile, &apd); - - /* settings for level 3 */ - RegSetValueExW(hdrv, Help_FileW, 0, REG_SZ, (LPBYTE) di.pHelpFile, - di.pHelpFile ? (lstrlenW(di.pHelpFile)+1)* sizeof(WCHAR) : 0); - apd_copyfile(di.pHelpFile, &apd); - - - ptr = di.pDependentFiles; - RegSetValueExW(hdrv, Dependent_FilesW, 0, REG_MULTI_SZ, (LPBYTE) di.pDependentFiles, - di.pDependentFiles ? multi_sz_lenW(di.pDependentFiles) : 0); - while ((ptr != NULL) && (ptr[0])) { - if (apd_copyfile(ptr, &apd)) { - ptr += lstrlenW(ptr) + 1; - } - else - { - WARN("Failed to copy %s\n", debugstr_w(ptr)); - ptr = NULL; - } - } - - /* The language-Monitor was already copied to "%SystemRoot%\system32" */ - RegSetValueExW(hdrv, MonitorW, 0, REG_SZ, (LPBYTE) di.pMonitorName, - di.pMonitorName ? (lstrlenW(di.pMonitorName)+1)* sizeof(WCHAR) : 0); - - RegSetValueExW(hdrv, DatatypeW, 0, REG_SZ, (LPBYTE) di.pDefaultDataType, - di.pDefaultDataType ? (lstrlenW(di.pDefaultDataType)+1)* sizeof(WCHAR) : 0); - - /* settings for level 4 */ - RegSetValueExW(hdrv, Previous_NamesW, 0, REG_MULTI_SZ, (LPBYTE) di.pszzPreviousNames, - di.pszzPreviousNames ? multi_sz_lenW(di.pszzPreviousNames) : 0); - - if (level > 5) FIXME("level %u for Driver %s is incomplete\n", level, debugstr_w(di.pName)); - - - RegCloseKey(hdrv); - FIXME("### DrvDriverEvent(...,DRIVEREVENT_INITIALIZE) not implemented yet\n"); - - - TRACE("=> TRUE with %u\n", GetLastError()); - return TRUE; - + return backend->fpAddPrinterDriverEx(pName, level, pDriverInfo, dwFileCopyFlags); } /****************************************************************************** diff --git a/dlls/winspool.drv/wspool.c b/dlls/winspool.drv/wspool.c index 27c39e6fa70..1685573a35a 100644 --- a/dlls/winspool.drv/wspool.c +++ b/dlls/winspool.drv/wspool.c @@ -27,10 +27,96 @@ #include "winbase.h" #include "wingdi.h" #include "winspool.h" + +#include "winreg.h" +#include "ddk/winsplp.h" +#include "wine/debug.h" + #include "wspool.h" +WINE_DEFAULT_DEBUG_CHANNEL(winspool); + +/* ############################### */ + +static CRITICAL_SECTION backend_cs; +static CRITICAL_SECTION_DEBUG backend_cs_debug = +{ + 0, 0, &backend_cs, + { &backend_cs_debug.ProcessLocksList, &backend_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": backend_cs") } +}; +static CRITICAL_SECTION backend_cs = { &backend_cs_debug, -1, 0, 0, 0, 0 }; + +/* ############################### */ + HINSTANCE WINSPOOL_hInstance = NULL; +static HMODULE hlocalspl = NULL; +static BOOL (WINAPI *pInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR); + +PRINTPROVIDOR * backend = NULL; + +/****************************************************************************** + * load_backend [internal] + * + * load and init our backend (the local printprovider: "localspl.dll") + * + * PARAMS + * + * RETURNS + * Success: TRUE + * Failure: FALSE and RPC_S_SERVER_UNAVAILABLE + * + * NOTES + * In windows, winspool.drv use RPC to interact with the spooler service + * (spoolsv.exe with spoolss.dll) and the spooler router (spoolss.dll) interact + * with the correct printprovider (localspl.dll for the local system) + * + */ +BOOL load_backend(void) +{ + static PRINTPROVIDOR mybackend; + DWORD res; + + EnterCriticalSection(&backend_cs); + hlocalspl = LoadLibraryA("localspl.dll"); + if (hlocalspl) { + pInitializePrintProvidor = (void *) GetProcAddress(hlocalspl, "InitializePrintProvidor"); + if (pInitializePrintProvidor) { + + /* native localspl does not clear unused entries */ + memset(&mybackend, 0, sizeof(mybackend)); + res = pInitializePrintProvidor(&mybackend, sizeof(mybackend), NULL); + if (res) { + backend = &mybackend; + LeaveCriticalSection(&backend_cs); + TRACE("backend: %p (%p)\n", backend, hlocalspl); + return TRUE; + } + } + FreeLibrary(hlocalspl); + } + + LeaveCriticalSection(&backend_cs); + + WARN("failed to load the backend: %u\n", GetLastError()); + SetLastError(RPC_S_SERVER_UNAVAILABLE); + return FALSE; +} + +/****************************************************************************** + * unload_backend [internal] + * + */ +void unload_backend(void) +{ + EnterCriticalSection(&backend_cs); + backend = NULL; + FreeLibrary(hlocalspl); + LeaveCriticalSection(&backend_cs); +} + + /****************************************************************************** * DllMain * @@ -48,6 +134,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD reason, LPVOID lpReserved) break; } case DLL_PROCESS_DETACH: + unload_backend(); break; } diff --git a/dlls/winspool.drv/wspool.h b/dlls/winspool.drv/wspool.h index 06178bc7fcd..5b831dc1f31 100644 --- a/dlls/winspool.drv/wspool.h +++ b/dlls/winspool.drv/wspool.h @@ -21,6 +21,9 @@ extern HINSTANCE WINSPOOL_hInstance; +extern PRINTPROVIDOR * backend; +extern BOOL load_backend(void); + extern void WINSPOOL_LoadSystemPrinters(void); #define IDS_CAPTION 10 diff --git a/dlls/wintab32/wintab32.c b/dlls/wintab32/wintab32.c index 5f8608b9d07..1ef19d904d0 100644 --- a/dlls/wintab32/wintab32.c +++ b/dlls/wintab32/wintab32.c @@ -143,8 +143,7 @@ static LRESULT WINAPI TABLET_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, { prox = MAKELPARAM( wParam, 1 ); TABLET_PostTabletMessage(handler, WT_PROXIMITY, - (WPARAM)handler->handle, (LPARAM)prox, - TRUE); + (WPARAM)handler->handle, prox, TRUE); } break; } diff --git a/dlls/wintrust/tests/crypt.c b/dlls/wintrust/tests/crypt.c index 600299aa497..887d57a7af5 100644 --- a/dlls/wintrust/tests/crypt.c +++ b/dlls/wintrust/tests/crypt.c @@ -30,33 +30,25 @@ static char selfname[MAX_PATH]; static CHAR CURR_DIR[MAX_PATH]; -static HMODULE hWintrust = 0; - static BOOL (WINAPI * pCryptCATAdminAcquireContext)(HCATADMIN*, const GUID*, DWORD); static BOOL (WINAPI * pCryptCATAdminReleaseContext)(HCATADMIN, DWORD); static BOOL (WINAPI * pCryptCATAdminCalcHashFromFileHandle)(HANDLE hFile, DWORD*, BYTE*, DWORD); +static void InitFunctionPtrs(void) +{ + HMODULE hWintrust = GetModuleHandleA("wintrust.dll"); + #define WINTRUST_GET_PROC(func) \ p ## func = (void*)GetProcAddress(hWintrust, #func); \ if(!p ## func) { \ trace("GetProcAddress(%s) failed\n", #func); \ } -static BOOL InitFunctionPtrs(void) -{ - hWintrust = LoadLibraryA("wintrust.dll"); - - if(!hWintrust) - { - skip("Could not load wintrust.dll\n"); - return FALSE; - } - WINTRUST_GET_PROC(CryptCATAdminAcquireContext) WINTRUST_GET_PROC(CryptCATAdminReleaseContext) WINTRUST_GET_PROC(CryptCATAdminCalcHashFromFileHandle) - return TRUE; +#undef WINTRUST_GET_PROC } static void test_context(void) @@ -290,8 +282,7 @@ START_TEST(crypt) int myARGC; char** myARGV; - if(!InitFunctionPtrs()) - return; + InitFunctionPtrs(); myARGC = winetest_get_mainargs(&myARGV); strcpy(selfname, myARGV[0]); @@ -300,6 +291,4 @@ START_TEST(crypt) test_context(); test_calchash(); - - FreeLibrary(hWintrust); } diff --git a/dlls/wnaspi32/winaspi16.c b/dlls/wnaspi32/winaspi16.c index ec451e45e77..b8dcf27538b 100644 --- a/dlls/wnaspi32/winaspi16.c +++ b/dlls/wnaspi32/winaspi16.c @@ -425,7 +425,7 @@ adapter name */ FIXME("Not implemented SC_GET_DEV_TYPE\n"); break; case SC_EXEC_SCSI_CMD: - return ASPI_ExecScsiCmd((DWORD)ptrSRB, mode); + return ASPI_ExecScsiCmd(ptrSRB, mode); case SC_RESET_DEV: FIXME("Not implemented SC_RESET_DEV\n"); break; diff --git a/dlls/ws2_32/async.c b/dlls/ws2_32/async.c index b9c745778f6..963ed661e2d 100644 --- a/dlls/ws2_32/async.c +++ b/dlls/ws2_32/async.c @@ -215,9 +215,9 @@ static int WS_copy_he(char *p_to,char *p_base,int t_size,struct hostent* p_he, i p_name = p; strcpy(p, p_he->h_name); p += strlen(p) + 1; p_aliases = p; - p += list_dup(p_he->h_aliases, p, p_base + (p - (char*)p_to), 0); + p += list_dup(p_he->h_aliases, p, p_base + (p - p_to), 0); p_addr = p; - list_dup(p_he->h_addr_list, p, p_base + (p - (char*)p_to), p_he->h_length); + list_dup(p_he->h_addr_list, p, p_base + (p - p_to), p_he->h_length); if (flag & AQ_WIN16) { @@ -273,7 +273,7 @@ static int WS_copy_pe(char *p_to,char *p_base,int t_size,struct protoent* p_pe, p_name = p; strcpy(p, p_pe->p_name); p += strlen(p) + 1; p_aliases = p; - list_dup(p_pe->p_aliases, p, p_base + (p - (char*)p_to), 0); + list_dup(p_pe->p_aliases, p, p_base + (p - p_to), 0); if (flag & AQ_WIN16) { @@ -630,7 +630,7 @@ HANDLE WINAPI WSAAsyncGetHostByName(HWND hWnd, UINT uMsg, LPCSTR name, LPSTR sbuf, INT buflen) { TRACE("hwnd %p, msg %08x, host %s, buffer %i\n", - hWnd, uMsg, (name)?name:"", (int)buflen ); + hWnd, uMsg, (name)?name:"", buflen ); return WSA_H32( __WSAsyncDBQuery(hWnd,uMsg,0,name,0,NULL,sbuf,buflen, AQ_NAME|AQ_DUPLOWPTR1|AQ_WIN32|AQ_GETHOST)); } diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 46083c7e5f0..fb6a20d1aaa 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1670,8 +1670,7 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, if ( (fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR; convert_sockopt(&level, &optname); - if (getsockopt(fd,(int) level, optname, optval, - (unsigned int *)optlen) != 0 ) + if (getsockopt(fd, level, optname, optval, (unsigned int *)optlen) != 0 ) { SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno()); ret = SOCKET_ERROR; @@ -1792,7 +1791,7 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, return SOCKET_ERROR; convert_sockopt(&level, &optname); - if (getsockopt(fd,(int) level, optname, &tv, &len) != 0 ) + if (getsockopt(fd, level, optname, &tv, &len) != 0 ) { SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno()); ret = SOCKET_ERROR; @@ -1886,8 +1885,7 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, if ( (fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR; convert_sockopt(&level, &optname); - if (getsockopt(fd,(int) level, optname, optval, - (unsigned int *)optlen) != 0 ) + if (getsockopt(fd, level, optname, optval, (unsigned int *)optlen) != 0 ) { SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno()); ret = SOCKET_ERROR; @@ -1915,8 +1913,7 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, if ( (fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR; convert_sockopt(&level, &optname); - if (getsockopt(fd,(int) level, optname, optval, - (unsigned int *)optlen) != 0 ) + if (getsockopt(fd, level, optname, optval, (unsigned int *)optlen) != 0 ) { SetLastError((errno == EBADF) ? WSAENOTSOCK : wsaErrno()); ret = SOCKET_ERROR; @@ -2292,6 +2289,11 @@ INT WINAPI WSAIoctl(SOCKET s, FIXME("SIO_FLUSH: stub.\n"); break; + case WS_SIO_GET_EXTENSION_FUNCTION_POINTER: + FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER %s: stub\n", debugstr_guid(lpvInBuffer)); + WSASetLastError(WSAEOPNOTSUPP); + return SOCKET_ERROR; + default: FIXME("unsupported WS_IOCTL cmd (%08x)\n", dwIoControlCode); WSASetLastError(WSAEOPNOTSUPP); diff --git a/include/Makefile.in b/include/Makefile.in index cde66cc1e34..7562ebed1a1 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -115,6 +115,7 @@ SRCDIR_INCLUDES = \ d3dx8core.h \ d3dx8math.h \ d3dx8math.inl \ + d3dx8mesh.h \ d3dx9.h \ d3dx9core.h \ d3dx9math.h \ diff --git a/include/d3dx8.h b/include/d3dx8.h index 52ddaf3f7c4..0ae27c3a52e 100644 --- a/include/d3dx8.h +++ b/include/d3dx8.h @@ -24,5 +24,9 @@ #include #include +/* FIXME: #include */ +#include +/* FIXME: #include */ +/* FIXME: #include */ #endif diff --git a/include/d3dx8core.h b/include/d3dx8core.h index 051deb70882..6de45833949 100644 --- a/include/d3dx8core.h +++ b/include/d3dx8core.h @@ -19,11 +19,7 @@ #ifndef __WINE_D3DX8CORE_H #define __WINE_D3DX8CORE_H -#include - #include -#include -#include /***************************************************************************** * #defines and error codes @@ -109,20 +105,26 @@ DECLARE_INTERFACE_(ID3DXFont,IUnknown) /************************************************************************************* * Define entrypoints */ -HRESULT WINAPI D3DXCreateBuffer(DWORD NumBytes, LPD3DXBUFFER* ppBuffer); +#ifdef __cplusplus +extern "C" { +#endif + HRESULT WINAPI D3DXCreateFont(LPDIRECT3DDEVICE8 pDevice, HFONT hFont, LPD3DXFONT* ppFont); -UINT WINAPI D3DXGetFVFVertexSize(DWORD FVF); HRESULT WINAPI D3DXAssembleShader(LPCVOID pSrcData, UINT SrcDataLen, DWORD Flags, LPD3DXBUFFER* ppConstants, LPD3DXBUFFER* ppCompiledShader, LPD3DXBUFFER* ppCompilationErrors); -HRESULT WINAPI D3DXAssembleShaderFromFileA(LPSTR pSrcFile, DWORD Flags, +HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR pSrcFile, DWORD Flags, LPD3DXBUFFER* ppConstants, LPD3DXBUFFER* ppCompiledShader, LPD3DXBUFFER* ppCompilationErrors); -HRESULT WINAPI D3DXAssembleShaderFromFileW(LPWSTR pSrcFile, DWORD Flags, +HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR pSrcFile, DWORD Flags, LPD3DXBUFFER* ppConstants, LPD3DXBUFFER* ppCompiledShader, LPD3DXBUFFER* ppCompilationErrors); +#ifdef __cplusplus +} +#endif + #endif /* __WINE_D3DX8CORE_H */ diff --git a/include/d3dx8math.h b/include/d3dx8math.h index 755698a0267..66d8fea3c9a 100644 --- a/include/d3dx8math.h +++ b/include/d3dx8math.h @@ -271,7 +271,7 @@ extern "C" { D3DXCOLOR* WINAPI D3DXColorAdjustContrast(D3DXCOLOR *pout, CONST D3DXCOLOR *pc, FLOAT s); D3DXCOLOR* WINAPI D3DXColorAdjustSaturation(D3DXCOLOR *pout, CONST D3DXCOLOR *pc, FLOAT s); -D3DXMATRIX* WINAPI D3DXMatrixAffineTransformation(D3DXMATRIX *pout, float scaling, D3DXVECTOR3 *rotationcenter, D3DXQUATERNION *rotation, D3DXVECTOR3 *translation); +D3DXMATRIX* WINAPI D3DXMatrixAffineTransformation(D3DXMATRIX *pout, FLOAT scaling, CONST D3DXVECTOR3 *rotationcenter, CONST D3DXQUATERNION *rotation, CONST D3DXVECTOR3 *translation); FLOAT WINAPI D3DXMatrixfDeterminant(CONST D3DXMATRIX *pm); D3DXMATRIX* WINAPI D3DXMatrixInverse(D3DXMATRIX *pout, FLOAT *pdeterminant, CONST D3DXMATRIX *pm); D3DXMATRIX* WINAPI D3DXMatrixLookAtLH(D3DXMATRIX *pout, CONST D3DXVECTOR3 *peye, CONST D3DXVECTOR3 *pat, CONST D3DXVECTOR3 *pup); diff --git a/include/d3dx8.h b/include/d3dx8mesh.h similarity index 71% copy from include/d3dx8.h copy to include/d3dx8mesh.h index 52ddaf3f7c4..f1eab5cd43c 100644 --- a/include/d3dx8.h +++ b/include/d3dx8mesh.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 David Adam + * Copyright (C) 2008 Francois Gouget * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,13 +16,21 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __D3DX8_H__ -#define __D3DX8_H__ +#ifndef __WINE_D3DX8MESH_H +#define __WINE_D3DX8MESH_H #include -#include +#include -#include -#include +#ifdef __cplusplus +extern "C" { +#endif + +HRESULT WINAPI D3DXCreateBuffer(DWORD,LPD3DXBUFFER*); +UINT WINAPI D3DXGetFVFVertexSize(DWORD); +#ifdef __cplusplus +} #endif + +#endif /* __WINE_D3DX8MESH_H */ diff --git a/include/gdiplusenums.h b/include/gdiplusenums.h index c625e684e2b..7c970058b56 100644 --- a/include/gdiplusenums.h +++ b/include/gdiplusenums.h @@ -124,6 +124,12 @@ enum InterpolationMode InterpolationModeHighQualityBicubic }; +enum PenAlignment +{ + PenAlignmentCenter = 0, + PenAlignmentInset = 1 +}; + enum PixelOffsetMode { PixelOffsetModeInvalid = QualityModeInvalid, @@ -279,6 +285,7 @@ typedef enum StringAlignment StringAlignment; typedef enum StringTrimming StringTrimming; typedef enum StringFormatFlags StringFormatFlags; typedef enum HotkeyPrefix HotkeyPrefix; +typedef enum PenAlignment GpPenAlignment; #endif /* end of c typedefs */ diff --git a/include/hlink.idl b/include/hlink.idl index 6cd84385df9..0eef883956b 100644 --- a/include/hlink.idl +++ b/include/hlink.idl @@ -35,6 +35,8 @@ cpp_quote("HRESULT WINAPI HlinkNavigate(IHlink*, IHlinkFrame*, DWORD, LPBC, IBin cpp_quote("HRESULT WINAPI HlinkOnNavigate(IHlinkFrame*, IHlinkBrowseContext*, DWORD, IMoniker*, LPCWSTR, LPCWSTR, ULONG*);") cpp_quote("HRESULT WINAPI HlinkIsShortcut(LPCWSTR);") cpp_quote("HRESULT WINAPI HlinkTranslateURL(LPCWSTR,DWORD,LPWSTR*);") +cpp_quote("HRESULT WINAPI HlinkParseDisplayName(LPBC,LPCWSTR,BOOL,ULONG*,IMoniker**);"); +cpp_quote("HRESULT WINAPI HlinkResolveMonikerForData(LPMONIKER,DWORD,LPBC,ULONG,FORMATETC*,IBindStatusCallback*,LPMONIKER);") typedef enum _HLSR_NOREDEF10 { HLSR_HOME, diff --git a/include/richedit.h b/include/richedit.h index ffbf661072d..cb278f654bb 100644 --- a/include/richedit.h +++ b/include/richedit.h @@ -531,7 +531,7 @@ typedef struct _gettextex { DWORD flags; UINT codepage; LPCSTR lpDefaultChar; - LPBOOL lpUsedDefaultChar; + LPBOOL lpUsedDefChar; } GETTEXTEX; #define SF_TEXT 0x00000001 diff --git a/include/shlobj.h b/include/shlobj.h index f57883a29dc..8dbccb75252 100644 --- a/include/shlobj.h +++ b/include/shlobj.h @@ -1033,6 +1033,10 @@ typedef enum { SLDF_NO_PIDL_ALIAS = 0x00008000, SLDF_FORCE_UNCNAME = 0x00010000, SLDF_RUN_WITH_SHIMLAYER = 0x00020000, + SLDF_FORCE_NO_LINKTRACK = 0x00040000, + SLDF_ENABLE_TARGET_METADATA = 0x00080000, + SLDF_DISABLE_KNOWNFOLDER_RELATIVE_TRACKING = 0x00200000, + SLDF_VALID = 0x003ff7ff, SLDF_RESERVED = 0x80000000, } SHELL_LINK_DATA_FLAGS; @@ -1062,13 +1066,20 @@ typedef struct { DWORD cbOffset; } EXP_SPECIAL_FOLDER, *LPEXP_SPECIAL_FOLDER; +typedef struct { + DWORD cbSize; + DWORD dwSignature; + BYTE abPropertyStorage[1]; +} EXP_PROPERTYSTORAGE; + #define EXP_SZ_LINK_SIG 0xa0000001 #define NT_CONSOLE_PROPS_SIG 0xa0000002 #define NT_FE_CONSOLE_PROPS_SIG 0xa0000004 #define EXP_SPECIAL_FOLDER_SIG 0xa0000005 #define EXP_DARWIN_ID_SIG 0xa0000006 -#define EXP_LOGO3_ID_SIG 0xa0000007 #define EXP_SZ_ICON_SIG 0xa0000007 +#define EXP_LOGO3_ID_SIG EXP_SZ_ICON_SIG /* Old SDKs only */ +#define EXP_PROPERTYSTORAGE_SIG 0xa0000009 typedef struct _SHChangeDWORDAsIDList { USHORT cb; diff --git a/include/urlmon.idl b/include/urlmon.idl index ab59c409385..d1da02a1130 100644 --- a/include/urlmon.idl +++ b/include/urlmon.idl @@ -1279,6 +1279,7 @@ cpp_quote("HRESULT WINAPI ObtainUserAgentString(DWORD,LPSTR,DWORD*);") cpp_quote("HRESULT WINAPI RegisterFormatEnumerator(LPBC,IEnumFORMATETC*,DWORD);") cpp_quote("HRESULT WINAPI RevokeFormatEnumerator(LPBC,IEnumFORMATETC*);") cpp_quote("HRESULT WINAPI RevokeBindStatusCallback(LPBC,IBindStatusCallback*);") +cpp_quote("HRESULT WINAPI CopyStgMedium(const STGMEDIUM*,STGMEDIUM*);") cpp_quote("void WINAPI ReleaseBindInfo(BINDINFO*);") cpp_quote("HRESULT WINAPI UrlMkGetSessionOption(DWORD,LPVOID,DWORD,DWORD*,DWORD);") cpp_quote("HRESULT WINAPI UrlMkSetSessionOption(DWORD,LPVOID,DWORD,DWORD);") diff --git a/include/uuids.h b/include/uuids.h index e3fb41b6de6..b767fccaba3 100644 --- a/include/uuids.h +++ b/include/uuids.h @@ -135,6 +135,7 @@ OUR_GUID_ENTRY(CLSID_QTDec, 0xfdfe9681, 0x74a3, 0x11d0, OUR_GUID_ENTRY(CLSID_AVIDoc, 0xd3588ab0, 0x0781, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70) OUR_GUID_ENTRY(CLSID_AVIDocWriter, 0xd3588ab1, 0x0781, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70) OUR_GUID_ENTRY(CLSID_VideoRenderer, 0x70e102b0, 0x5556, 0x11ce, 0x97, 0xc0, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a) +OUR_GUID_ENTRY(CLSID_VideoRendererDefault, 0x6bc1cffa, 0x8fc1, 0x4261, 0xac, 0x22, 0xcf, 0xb4, 0xcc, 0x38, 0xdb, 0x50) OUR_GUID_ENTRY(CLSID_Colour, 0x1643e180, 0x90f5, 0x11ce, 0x97, 0xd5, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a) OUR_GUID_ENTRY(CLSID_Dither, 0x1da08500, 0x9edc, 0x11cf, 0xbc, 0x10, 0x00, 0xaa, 0x00, 0xac, 0x74, 0xf6) OUR_GUID_ENTRY(CLSID_ModexRenderer, 0x07167665, 0x5011, 0x11cf, 0xbf, 0x33, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a) diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h index da486d9d44f..8ea37e1d455 100644 --- a/include/wine/mscvpdb.h +++ b/include/wine/mscvpdb.h @@ -343,9 +343,9 @@ union codeview_type { unsigned short int len; short int id; - unsigned this_type; - unsigned int class_type; unsigned int rvtype; + unsigned int class_type; + unsigned this_type; unsigned char call; unsigned char reserved; unsigned short params; @@ -732,7 +732,17 @@ union codeview_fieldtype * bit mode. There are many other types listed in the documents, but these * are apparently not used by the compiler, or represent pointer types * that are not used. + * + * Official MS documentation says that type (< 0x4000, so 12 bits) is made of: + * +----------+------+------+----------+------+ + * | 11 | 10-8 | 7-4 | 3 | 2-0 | + * +----------+------+------+----------+------+ + * | reserved | mode | type | reserved | size | + * +----------+------+------+----------+------+ + * In recent PDB files, type 8 exists, and is seen as an HRESULT... So we've + * added this basic type... as if bit 3 had been integrated into the size field */ + /* the type number of a built-in type is a 16-bit value specified in the following format: bit # | 11 | 10-8 | 7-4 | 3 | 2-0 | field | reserved | mode | type | reserved | size | @@ -817,6 +827,7 @@ union codeview_fieldtype #define T_NBASICSTR 0x0005 /* near basic string */ #define T_FBASICSTR 0x0006 /* far basic string */ #define T_NOTTRANS 0x0007 /* untranslated type record from MS symbol format */ +#define T_HRESULT 0x0008 /* Hresult - or error code ??? */ #define T_CHAR 0x0010 /* signed char */ #define T_SHORT 0x0011 /* short */ #define T_LONG 0x0012 /* long */ @@ -951,6 +962,7 @@ union codeview_fieldtype /* 32-bit near pointers to basic types */ #define T_32PVOID 0x0403 /* 32-bit near pointer to void */ +#define T_32PHRESULT 0x0408 /* 16:32 near pointer to Hresult - or error code ??? */ #define T_32PCHAR 0x0410 /* 16:32 near pointer to 8-bit signed */ #define T_32PSHORT 0x0411 /* 16:32 near pointer to 16-bit signed */ #define T_32PLONG 0x0412 /* 16:32 near pointer to 32-bit signed */ @@ -1032,8 +1044,6 @@ union codeview_fieldtype #define T_FAR32PTR_BITS 0x0500 #define T_NEAR64PTR_BITS 0x0600 - - #define LF_MODIFIER_V1 0x0001 #define LF_POINTER_V1 0x0002 #define LF_ARRAY_V1 0x0003 @@ -1333,6 +1343,16 @@ union codeview_symbol struct { + short int len; /* Total length of this entry */ + short int id; /* Always S_BPREL_V3 */ + int offset; /* Stack offset relative to BP */ + unsigned int symtype; + unsigned short unknown; + char name[1]; + } stack_xxxx_v3; + + struct + { short int len; /* Total length of this entry */ short int id; /* Always S_REGISTER */ unsigned short type; @@ -1573,6 +1593,7 @@ union codeview_symbol #define S_PUB_V3 0x110E #define S_LPROC_V3 0x110F #define S_GPROC_V3 0x1110 +#define S_BPREL_XXXX_V3 0x1111 /* not really understood, but looks like bprel... */ #define S_MSTOOL_V3 0x1116 /* compiler command line options and build information */ #define S_PUB_FUNC1_V3 0x1125 /* didn't get the difference between the two */ #define S_PUB_FUNC2_V3 0x1127 diff --git a/include/wine/test.h b/include/wine/test.h index dbce98c4479..32850ceec84 100644 --- a/include/wine/test.h +++ b/include/wine/test.h @@ -57,6 +57,7 @@ extern void winetest_start_todo( const char* platform ); extern int winetest_loop_todo(void); extern void winetest_end_todo( const char* platform ); extern int winetest_get_mainargs( char*** pargv ); +extern void winetest_wait_child_process( HANDLE process ); #ifdef STANDALONE #define START_TEST(name) \ @@ -340,6 +341,23 @@ int winetest_get_mainargs( char*** pargv ) return winetest_argc; } +void winetest_wait_child_process( HANDLE process ) +{ + DWORD exit_code = 1; + + if (WaitForSingleObject( process, 30000 )) + fprintf( stdout, "%s: child process wait failed\n", current_test->name ); + else + GetExitCodeProcess( process, &exit_code ); + + if (exit_code) + { + fprintf( stdout, "%s: %u failures in child process\n", + current_test->name, exit_code ); + InterlockedExchangeAdd( &failures, exit_code ); + } +} + /* Find a test by name */ static const struct test *find_test( const char *name ) { diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h index 4379039bef4..b6913fb9909 100644 --- a/include/wine/wined3d_gl.h +++ b/include/wine/wined3d_gl.h @@ -3653,7 +3653,8 @@ typedef struct _WineD3D_GL_Info { GL_Vendors gl_vendor; GL_Cards gl_card; UINT vidmem; - DWORD gl_driver_version; + DWORD driver_version; + DWORD driver_version_hipart; CHAR gl_renderer[255]; /** * CAPS Constants diff --git a/include/wintrust.h b/include/wintrust.h index 0c4d53583a9..bc1c3678b8c 100644 --- a/include/wintrust.h +++ b/include/wintrust.h @@ -341,6 +341,8 @@ typedef struct _CRYPT_PROVIDER_DATA { HCRYPTMSG hMsg; DWORD csSigners; CRYPT_PROVIDER_SGNR *pasSigners; + DWORD csProvPrivData; + CRYPT_PROVIDER_PRIVDATA *pasProvPrivData; DWORD dwSubjectChoice; union { struct _PROVDATA_SIP *pPDSip; diff --git a/include/winuser.h b/include/winuser.h index aec4a8399a4..6e61e1067d7 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -4482,7 +4482,7 @@ WINUSERAPI BOOL WINAPI EnableScrollBar(HWND,UINT,UINT); WINUSERAPI BOOL WINAPI EnableWindow(HWND,BOOL); WINUSERAPI BOOL WINAPI EndDeferWindowPos(HDWP); WINUSERAPI BOOL WINAPI EndDialog(HWND,INT_PTR); -WINUSERAPI VOID WINAPI EndMenu(void); +WINUSERAPI BOOL WINAPI EndMenu(void); WINUSERAPI BOOL WINAPI EndPaint(HWND,const PAINTSTRUCT*); WINUSERAPI BOOL WINAPI EnumChildWindows(HWND,WNDENUMPROC,LPARAM); WINUSERAPI UINT WINAPI EnumClipboardFormats(UINT); diff --git a/programs/cmd/Ru.rc b/programs/cmd/Ru.rc index 7e084800847..acc8394b4bc 100644 --- a/programs/cmd/Ru.rc +++ b/programs/cmd/Ru.rc @@ -202,10 +202,10 @@ VERIFY WCMD_VOL, "Ñïðàâêà î VOL\n" - WCMD_PUSHD, "PUSHD saves the current directory onto a\n\ -stack, and then changes the current directory to the supplied one.\n" + WCMD_PUSHD, "PUSHD ñîõðàíÿåò òåêóùèé êàòàëîã â ñòåê,\n\ +à çàòåì ïåðåõîäèò â óêàçàííûé êàòàëîã.\n" - WCMD_POPD, "POPD changes current directory to the last one saved with\n\ + WCMD_POPD, "POPD ïåðåõîäèò â êàòàëîã, ñîõðàí¸ííûé êîìàíäîé\n\ PUSHD.\n" WCMD_MORE, "MORE displays output of files or piped input in pages.\n" @@ -225,13 +225,13 @@ DATE\t\t DEL (ERASE)\tÓäàëèòü ôàéë èëè íàáîð ôàéëîâ\n\ DIR\t\tÏîêàçàòü ñîäåðæàíèå ïàïêè\n\ ECHO\t\tÑêîïèðîâàòü òåêñò ïðÿìî íà âûõîä êîíñîëè\n\ -HELP\t\tÏîêàçàòü êðàäêóþ ïîäñêàçêó ïî êîìàíäå\n\ +HELP\t\tÏîêàçàòü êðàòêóþ ïîäñêàçêó ïî êîìàíäå\n\ MD (MKDIR)\tÑîçäàòü ïàïêó\n\ -MORE\t\tDisplay output in pages\n\ +MORE\t\tÂûâåñòè äàííûå ïî ñòðàíèöàì\n\ MOVE\t\tÏåðåìåñòèòü ôàéë, íàáîð ôàéëîâ èëè äåðåâî ïàïîê\n\ PATH\t\tÏîêàçàòü èëè èçìåíèòü ïóòü ïîèñêà ïðîãðàìì\n\ -POPD\t\tRestores the directory to the last one saved with PUSHD\n\ -PUSHD\t\tChanges to a new directory, saving the current one\n\ +POPD\t\tÂîññòàíîâèòü ïðåäûäóùåå çíà÷åíèå òåêóùåé ïàïêè, ñîõðàí¸ííîãî ñ ïîìîùüþ PUSHD\n\ +PUSHD\t\tÑîõðàíèòü çíà÷åíèå òåêóùåé ïàïêè è ïåðåõîäèò ê äðóãîé ïàïêå\n\ PROMPT\t\tÈçìåíèòü ïðèãëàøåíèå êîìàíäíîé ñòðîêè\n\ REN (RENAME)\tÏåðåèìåíîâàòü ôàéë\n\ RD (RMDIR)\tÓäàëèòü ïàïêó\n\ @@ -277,5 +277,5 @@ EXIT\t\t WCMD_ANYKEY,"Íàæìèòå ââîä äëÿ ïðîäîëæåíèÿ: " WCMD_CONSTITLE,"Ïðèãëàøåíèå êîìàíäíîé ñòðîêè Wine" WCMD_VERSION,"Âåðñèÿ CMD %s\n\n" - WCMD_MOREPROMPT, "More? " + WCMD_MOREPROMPT, "Åù¸? " } diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c index 06347d4a503..9ddfd4d4ccd 100644 --- a/programs/explorer/systray.c +++ b/programs/explorer/systray.c @@ -64,6 +64,7 @@ struct icon HWND tooltip; /* Icon tooltip */ UINT id; /* the unique id given by the app */ UINT callback_message; + BOOL hidden; /* icon display state */ }; static struct tray tray; @@ -182,68 +183,24 @@ static void set_tooltip(struct icon *icon, WCHAR *szTip, BOOL modify) SendMessageW(icon->tooltip, TTM_ADDTOOLW, 0, (LPARAM)&ti); } -static void modify_icon(NOTIFYICONDATAW *nid, BOOL modify_tooltip) +static BOOL display_icon(struct icon *icon, BOOL hide) { - struct icon *icon; - - WINE_TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd); - - /* demarshal the request from the NID */ - icon = get_icon(nid->hWnd, nid->uID); - if (!icon) - { - WINE_WARN("Invalid icon ID (0x%x) for HWND %p\n", nid->uID, nid->hWnd); - return; - } - - if (nid->uFlags & NIF_ICON) - { - if (icon->image) DestroyIcon(icon->image); - icon->image = CopyIcon(nid->hIcon); - - RedrawWindow(icon->window, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); - } - - if (nid->uFlags & NIF_MESSAGE) - { - icon->callback_message = nid->uCallbackMessage; - } - if (nid->uFlags & NIF_TIP) - { - set_tooltip(icon, nid->szTip, modify_tooltip); - } - if (nid->uFlags & NIF_INFO && nid->cbSize >= NOTIFYICONDATAA_V2_SIZE) - { - WINE_FIXME("balloon tip title %s, message %s\n", wine_dbgstr_w(nid->szInfoTitle), wine_dbgstr_w(nid->szInfo)); - } -} - -static void add_icon(NOTIFYICONDATAW *nid) -{ - HMODULE x11drv = GetModuleHandleA( "winex11.drv" ); + HMODULE x11drv = GetModuleHandleA("winex11.drv"); RECT rect; - struct icon *icon; static const WCHAR adaptor_windowname[] = /* Wine System Tray Adaptor */ {'W','i','n','e',' ','S','y','s','t','e','m',' ','T','r','a','y',' ','A','d','a','p','t','o','r',0}; static BOOL tooltps_initialized = FALSE; - WINE_TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd); - - if ((icon = get_icon(nid->hWnd, nid->uID))) - { - WINE_WARN("duplicate tray icon add, buggy app?\n"); - return; - } + WINE_TRACE("id=0x%x, hwnd=%p, hide=%d\n", icon->id, icon->owner, hide); - if (!(icon = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*icon)))) + if (icon->hidden == hide || (!icon->hidden) == (!hide)) return TRUE; + icon->hidden = hide; + if (hide) { - WINE_ERR("out of memory\n"); - return; + DestroyWindow(icon->window); + DestroyWindow(icon->tooltip); + return TRUE; } - icon->id = nid->uID; - icon->owner = nid->hWnd; - icon->image = NULL; - rect.left = 0; rect.top = 0; rect.right = GetSystemMetrics(SM_CXSMICON) + ICON_BORDER; @@ -260,8 +217,8 @@ static void add_icon(NOTIFYICONDATAW *nid) NULL, NULL, NULL, icon); if (x11drv) { - void (*make_systray_window)(HWND) = (void *)GetProcAddress( x11drv, "wine_make_systray_window" ); - if (make_systray_window) make_systray_window( icon->window ); + void (*make_systray_window)(HWND) = (void *)GetProcAddress(x11drv, "wine_make_systray_window"); + if (make_systray_window) make_systray_window(icon->window); } if (!hide_systray) @@ -286,13 +243,87 @@ static void add_icon(NOTIFYICONDATAW *nid) CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, icon->window, NULL, NULL, NULL); + return TRUE; +} + +static BOOL modify_icon(NOTIFYICONDATAW *nid, BOOL modify_tooltip) +{ + struct icon *icon; + + WINE_TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd); + + /* demarshal the request from the NID */ + icon = get_icon(nid->hWnd, nid->uID); + if (!icon) + { + WINE_WARN("Invalid icon ID (0x%x) for HWND %p\n", nid->uID, nid->hWnd); + return FALSE; + } + + if (nid->uFlags & NIF_STATE) + { + if (nid->dwStateMask & NIS_HIDDEN) + display_icon(icon, !!(nid->dwState & NIS_HIDDEN)); + else + display_icon(icon, FALSE); + } + else + display_icon(icon, FALSE); + + if (nid->uFlags & NIF_ICON) + { + if (icon->image) DestroyIcon(icon->image); + icon->image = CopyIcon(nid->hIcon); + + if (!icon->hidden) + RedrawWindow(icon->window, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); + } + + if (nid->uFlags & NIF_MESSAGE) + { + icon->callback_message = nid->uCallbackMessage; + } + if (nid->uFlags & NIF_TIP) + { + set_tooltip(icon, nid->szTip, modify_tooltip); + } + if (nid->uFlags & NIF_INFO && nid->cbSize >= NOTIFYICONDATAA_V2_SIZE) + { + WINE_FIXME("balloon tip title %s, message %s\n", wine_dbgstr_w(nid->szInfoTitle), wine_dbgstr_w(nid->szInfo)); + } + return TRUE; +} + +static BOOL add_icon(NOTIFYICONDATAW *nid) +{ + struct icon *icon; + + WINE_TRACE("id=0x%x, hwnd=%p\n", nid->uID, nid->hWnd); + + if ((icon = get_icon(nid->hWnd, nid->uID))) + { + WINE_WARN("duplicate tray icon add, buggy app?\n"); + return FALSE; + } + + if (!(icon = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*icon)))) + { + WINE_ERR("out of memory\n"); + return FALSE; + } + + icon->id = nid->uID; + icon->owner = nid->hWnd; + icon->image = NULL; + icon->window = NULL; + icon->hidden = TRUE; list_add_tail(&tray.icons, &icon->entry); - modify_icon(nid, FALSE); + return modify_icon(nid, FALSE); } -static void delete_icon(const NOTIFYICONDATAW *nid) +static BOOL delete_icon(const NOTIFYICONDATAW *nid) { struct icon *icon = get_icon(nid->hWnd, nid->uID); @@ -300,22 +331,23 @@ static void delete_icon(const NOTIFYICONDATAW *nid) if (!icon) { - WINE_ERR("invalid tray icon ID specified: %u\n", nid->uID); - return; + WINE_WARN("invalid tray icon ID specified: %u\n", nid->uID); + return FALSE; } - DestroyWindow(icon->tooltip); - DestroyWindow(icon->window); + display_icon(icon, TRUE); + return TRUE; } -static void handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds) +static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds) { NOTIFYICONDATAW nid; DWORD cbSize; + BOOL ret = FALSE; - if (cds->cbData < NOTIFYICONDATAW_V1_SIZE) return; + if (cds->cbData < NOTIFYICONDATAW_V1_SIZE) return FALSE; cbSize = ((PNOTIFYICONDATA)cds->lpData)->cbSize; - if (cbSize < NOTIFYICONDATAW_V1_SIZE) return; + if (cbSize < NOTIFYICONDATAW_V1_SIZE) return FALSE; ZeroMemory(&nid, sizeof(nid)); memcpy(&nid, cds->lpData, min(sizeof(nid), cbSize)); @@ -343,14 +375,14 @@ static void handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds) if (cds->cbData < nid.cbSize + 2 * sizeof(BITMAP) + cbMaskBits + cbColourBits) { WINE_ERR("buffer underflow\n"); - return; + return FALSE; } /* sanity check */ if ((bmColour.bmWidth != bmMask.bmWidth) || (bmColour.bmHeight != bmMask.bmHeight)) { WINE_ERR("colour and mask bitmaps aren't consistent\n"); - return; + return FALSE; } nid.hIcon = CreateIcon(NULL, bmColour.bmWidth, bmColour.bmHeight, @@ -361,13 +393,13 @@ static void handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds) switch (cds->dwData) { case NIM_ADD: - add_icon(&nid); + ret = add_icon(&nid); break; case NIM_DELETE: - delete_icon(&nid); + ret = delete_icon(&nid); break; case NIM_MODIFY: - modify_icon(&nid, TRUE); + ret = modify_icon(&nid, TRUE); break; default: WINE_FIXME("unhandled tray message: %ld\n", cds->dwData); @@ -378,13 +410,15 @@ static void handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds) * icon handles */ if (nid.uFlags & NIF_ICON) DestroyIcon(nid.hIcon); + + return ret; } static LRESULT WINAPI listener_wndproc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) { if (msg == WM_COPYDATA) - handle_incoming((HWND)wparam, (COPYDATASTRUCT *)lparam); + return handle_incoming((HWND)wparam, (COPYDATASTRUCT *)lparam); return DefWindowProc(window, msg, wparam, lparam); } diff --git a/programs/winecfg/libraries.c b/programs/winecfg/libraries.c index 8e4e46bbb7c..aa0a1614901 100644 --- a/programs/winecfg/libraries.c +++ b/programs/winecfg/libraries.c @@ -408,10 +408,14 @@ static void init_libsheet(HWND dialog) static void on_add_combo_change(HWND dialog) { char buffer[1024]; + int sel, len; SendDlgItemMessage(dialog, IDC_DLLCOMBO, WM_GETTEXT, sizeof(buffer), (LPARAM) buffer); + /* if lib was chosen from combobox, we reveive an empty buffer, check manually */ + sel=SendDlgItemMessage(dialog, IDC_DLLCOMBO, CB_GETCURSEL, 0, 0); + len=SendDlgItemMessage(dialog, IDC_DLLCOMBO, CB_GETLBTEXTLEN, sel, 0); - if (strlen(buffer)) + if (strlen(buffer)>0 || len>0) enable(IDC_DLLS_ADDDLL) else disable(IDC_DLLS_ADDDLL); diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c index 4f83c72941f..d68bff47a27 100644 --- a/programs/winedbg/gdbproxy.c +++ b/programs/winedbg/gdbproxy.c @@ -1385,6 +1385,33 @@ static enum packet_return packet_write_memory(struct gdb_context* gdbctx) return packet_ok; /* FIXME: error while writing ? */ } +static enum packet_return packet_read_register(struct gdb_context* gdbctx) +{ + unsigned reg; + CONTEXT ctx; + CONTEXT* pctx = &gdbctx->context; + + assert(gdbctx->in_trap); + reg = hex_to_int(gdbctx->in_packet, gdbctx->in_packet_len); + if (reg >= cpu_num_regs) + { + if (gdbctx->trace & GDBPXY_TRC_COMMAND_ERROR) + fprintf(stderr, "Register out of bounds %x (%x)\n", reg, cpu_num_regs); + return packet_error; + } + if (dbg_curr_thread != gdbctx->other_thread && gdbctx->other_thread) + { + if (!fetch_context(gdbctx, gdbctx->other_thread->handle, pctx = &ctx)) + return packet_error; + } + if (gdbctx->trace & GDBPXY_TRC_COMMAND) + fprintf(stderr, "Read register %x => %lx\n", reg, *cpu_register(pctx, reg)); + packet_reply_open(gdbctx); + packet_reply_hex_to(gdbctx, cpu_register(pctx, reg), 4); + packet_reply_close(gdbctx); + return packet_done; +} + static enum packet_return packet_write_register(struct gdb_context* gdbctx) { unsigned reg; @@ -1931,7 +1958,7 @@ static struct packet_entry packet_entries[] = {'H', packet_thread}, {'m', packet_read_memory}, {'M', packet_write_memory}, - /* {'p', packet_read_register}, doesn't seem needed */ + {'p', packet_read_register}, {'P', packet_write_register}, {'q', packet_query}, /* {'Q', packet_set}, */ diff --git a/programs/wordpad/registry.c b/programs/wordpad/registry.c index 196e7d1a073..aef152a235a 100644 --- a/programs/wordpad/registry.c +++ b/programs/wordpad/registry.c @@ -187,7 +187,7 @@ static void format_filelist_filename(LPWSTR file, LPWSTR out) else if(truncpos1 == truncpos2 || !truncpos2) lstrcatW(out, file); else - truncate_path(file, out, truncpos1, truncpos2 ? truncpos2 : (pos_basename-1)); + truncate_path(file, out, truncpos1, truncpos2); } void registry_read_filelist(HWND hMainWnd) diff --git a/server/named_pipe.c b/server/named_pipe.c index 659d680162d..6db9a7a05c2 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -772,11 +772,20 @@ static struct pipe_server *find_available_server( struct named_pipe *pipe ) { struct pipe_server *server; + /* look for pipe servers that are listening */ LIST_FOR_EACH_ENTRY( server, &pipe->servers, struct pipe_server, entry ) { - if (server->state == ps_idle_server || server->state == ps_wait_open) + if (server->state == ps_wait_open) return (struct pipe_server *)grab_object( server ); } + + /* fall back to pipe servers that are idle */ + LIST_FOR_EACH_ENTRY( server, &pipe->servers, struct pipe_server, entry ) + { + if (server->state == ps_idle_server) + return (struct pipe_server *)grab_object( server ); + } + return NULL; } diff --git a/tools/widl/client.c b/tools/widl/client.c index 5cd2a81800b..2eaa43c9848 100644 --- a/tools/widl/client.c +++ b/tools/widl/client.c @@ -85,6 +85,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) { const var_t *def = func->def; const var_t* explicit_handle_var; + int has_full_pointer = is_full_pointer_function(func); /* check for a defined binding handle */ explicit_handle_var = get_explicit_handle_var(func); @@ -142,6 +143,9 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) } fprintf(client, "\n"); + if (has_full_pointer) + write_full_pointer_init(client, indent, func, FALSE); + /* check pointers */ check_pointers(func); @@ -245,6 +249,9 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) /* FIXME: emit client finally code */ + if (has_full_pointer) + write_full_pointer_free(client, indent, func); + print_client("NdrFreeBuffer((PMIDL_STUB_MESSAGE)&_StubMsg);\n"); indent--; diff --git a/tools/widl/parser.l b/tools/widl/parser.l index 98f17af45fb..2497a5e062a 100644 --- a/tools/widl/parser.l +++ b/tools/widl/parser.l @@ -414,7 +414,11 @@ int do_import(char *fname) import->next = first_import; first_import = import; - if (!(path = wpp_find_include( fname, input_name ))) + /* don't search for a file name with a path in the include directories, + * for compatibility with MIDL */ + if (strchr( fname, '/' ) || strchr( fname, '\\' )) + path = strdup( fname ); + else if (!(path = wpp_find_include( fname, input_name ))) error_loc("Unable to open include file %s\n", fname); import_stack[ptr].temp_name = temp_name; diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c index 731629f732c..217c64bf3cd 100644 --- a/tools/widl/proxy.c +++ b/tools/widl/proxy.c @@ -254,6 +254,7 @@ static void gen_proxy(type_t *iface, const func_t *cur, int idx, { var_t *def = cur->def; int has_ret = !is_void(def->type); + int has_full_pointer = is_full_pointer_function(cur); indent = 0; write_type_decl_left(proxy, def->type); @@ -279,6 +280,9 @@ static void gen_proxy(type_t *iface, const func_t *cur, int idx, } print_proxy( "\n"); + if (has_full_pointer) + write_full_pointer_init(proxy, indent, cur, FALSE); + /* FIXME: trace */ clear_output_vars( cur->args ); @@ -325,6 +329,8 @@ static void gen_proxy(type_t *iface, const func_t *cur, int idx, print_proxy( "RpcFinally\n" ); print_proxy( "{\n" ); indent++; + if (has_full_pointer) + write_full_pointer_free(proxy, indent, cur); print_proxy( "NdrProxyFreeBuffer(This, &_StubMsg);\n" ); indent--; print_proxy( "}\n"); @@ -356,6 +362,7 @@ static void gen_stub(type_t *iface, const func_t *cur, const char *cas, var_t *def = cur->def; const var_t *arg; int has_ret = !is_void(def->type); + int has_full_pointer = is_full_pointer_function(cur); indent = 0; print_proxy( "void __RPC_STUB %s_", iface->name); @@ -384,6 +391,8 @@ static void gen_stub(type_t *iface, const func_t *cur, const char *cas, print_proxy("RpcTryFinally\n"); print_proxy("{\n"); indent++; + if (has_full_pointer) + write_full_pointer_init(proxy, indent, cur, TRUE); print_proxy("if ((_pRpcMessage->DataRepresentation & 0xffff) != NDR_LOCAL_DATA_REPRESENTATION)\n"); indent++; print_proxy("NdrConvert( &_StubMsg, &__MIDL_ProcFormatString.Format[%u]);\n", proc_offset ); @@ -439,6 +448,9 @@ static void gen_stub(type_t *iface, const func_t *cur, const char *cas, write_remoting_arguments(proxy, indent+1, cur, PASS_OUT, PHASE_FREE); + if (has_full_pointer) + write_full_pointer_free(proxy, indent, cur); + print_proxy("}\n"); print_proxy("RpcEndFinally\n"); diff --git a/tools/widl/server.c b/tools/widl/server.c index 3bcd2319ea2..53dd099cab2 100644 --- a/tools/widl/server.c +++ b/tools/widl/server.c @@ -62,6 +62,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) LIST_FOR_EACH_ENTRY( func, iface->funcs, const func_t, entry ) { const var_t *def = func->def; + int has_full_pointer = is_full_pointer_function(func); /* check for a defined binding handle */ explicit_handle_var = get_explicit_handle_var(func); @@ -126,6 +127,9 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) print_server("{\n"); indent++; + if (has_full_pointer) + write_full_pointer_init(server, indent, func, TRUE); + if (func->args) { print_server("if ((_pRpcMessage->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n"); @@ -236,6 +240,9 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset) write_remoting_arguments(server, indent, func, PASS_OUT, PHASE_FREE); + if (has_full_pointer) + write_full_pointer_free(server, indent, func); + indent--; print_server("}\n"); print_server("RpcEndFinally\n"); diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 0e8a09681b8..41dd22f2cfd 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -193,6 +193,46 @@ static int type_has_pointers(const type_t *type) return FALSE; } +static int type_has_full_pointer(const type_t *type) +{ + if (is_user_type(type)) + return FALSE; + else if (type->type == RPC_FC_FP) + return TRUE; + else if (is_ptr(type)) + return FALSE; + else if (is_array(type)) + return type_has_full_pointer(type->ref); + else if (is_struct(type->type)) + { + const var_t *field; + if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry ) + { + if (type_has_full_pointer(field->type)) + return TRUE; + } + } + else if (is_union(type->type)) + { + var_list_t *fields; + const var_t *field; + if (type->type == RPC_FC_ENCAPSULATED_UNION) + { + const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry); + fields = uv->type->fields; + } + else + fields = type->fields; + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) + { + if (field->type && type_has_full_pointer(field->type)) + return TRUE; + } + } + + return FALSE; +} + static unsigned short user_type_offset(const char *name) { user_type_t *ut; @@ -903,6 +943,32 @@ size_t type_memsize(const type_t *t, unsigned int *align) return size; } +int is_full_pointer_function(const func_t *func) +{ + const var_t *var; + if (type_has_full_pointer(func->def->type)) + return TRUE; + if (!func->args) + return FALSE; + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + if (type_has_full_pointer( var->type )) + return TRUE; + return FALSE; +} + +void write_full_pointer_init(FILE *file, int indent, const func_t *func, int is_server) +{ + print_file(file, indent, "_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n", + is_server ? "XLAT_SERVER" : "XLAT_CLIENT"); + fprintf(file, "\n"); +} + +void write_full_pointer_free(FILE *file, int indent, const func_t *func) +{ + print_file(file, indent, "NdrFullPointerXlatFree(_StubMsg.FullPtrXlatTables);\n"); + fprintf(file, "\n"); +} + static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset) { short absoff = type->ref->typestring_offset; diff --git a/tools/widl/typegen.h b/tools/widl/typegen.h index c9a5148290f..4408ffa75ec 100644 --- a/tools/widl/typegen.h +++ b/tools/widl/typegen.h @@ -60,3 +60,6 @@ void print(FILE *file, int indent, const char *format, va_list ap); int get_padding(const var_list_t *fields); int is_user_type(const type_t *t); expr_t *get_size_is_expr(const type_t *t, const char *name); +int is_full_pointer_function(const func_t *func); +void write_full_pointer_init(FILE *file, int indent, const func_t *func, int is_server); +void write_full_pointer_free(FILE *file, int indent, const func_t *func); diff --git a/tools/widl/utils.c b/tools/widl/utils.c index e77361ce339..ed950f6095d 100644 --- a/tools/widl/utils.c +++ b/tools/widl/utils.c @@ -136,6 +136,9 @@ char *dup_basename(const char *name, const char *ext) name = "widl.tab"; slash = strrchr(name, '/'); + if (!slash) + slash = strrchr(name, '\\'); + if (slash) name = slash + 1; diff --git a/tools/widl/widl.c b/tools/widl/widl.c index 79456942609..07f024cea1d 100644 --- a/tools/widl/widl.c +++ b/tools/widl/widl.c @@ -166,6 +166,9 @@ static char *make_token(const char *name) int i; slash = strrchr(name, '/'); + if(!slash) + slash = strrchr(name, '\\'); + if (slash) name = slash + 1; token = xstrdup(name); diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index f5ea2f7f27b..4e7edf3a150 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -1841,6 +1841,9 @@ static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_ typeinfo->flags |= 0x10; /* TYPEFLAG_FHIDDEN */ break; + case ATTR_LOCAL: + break; + case ATTR_NONCREATABLE: typeinfo->flags &= ~0x2; /* TYPEFLAG_FCANCREATE */ break; @@ -2415,7 +2418,7 @@ static int save_all_changes(msft_typelib_t *typelib) retval = TYPE_E_IOERROR; - fd = creat(typelib->typelib->filename, 0666); + fd = open(typelib->typelib->filename, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0666); if (fd == -1) return retval; filepos = sizeof(MSFT_Header) + sizeof(MSFT_SegDir); diff --git a/tools/winapi/win32.api b/tools/winapi/win32.api index 067ee40b44a..1fd1697ed4b 100644 --- a/tools/winapi/win32.api +++ b/tools/winapi/win32.api @@ -1,3 +1,11 @@ +%%acledit.dll + +%long + +HWND +LONG +WORD + %%activeds.dll %long @@ -115,7 +123,11 @@ PACL * PACTRL_ACCESSW * PACTRL_AUDITW * PBOOL +PCREDENTIALA +PCREDENTIALA * PCREDENTIALA ** +PCREDENTIALW +PCREDENTIALW * PCREDENTIALW ** PDWORD PEXPLICIT_ACCESSA @@ -860,6 +872,18 @@ int void +%%ctapi32.dll + +%long + +IS8 +IU16 + +%ptr + +IU8 * +IU16 * + %%d3d8.dll %long @@ -909,16 +933,38 @@ HFONT HRESULT UINT +%float + +FLOAT + %ptr +D3DXCOLOR * +D3DXMATRIX * +D3DXPLANE * +D3DXQUATERNION * +D3DXVECTOR2 * +D3DXVECTOR3 * +D3DXVECTOR4 * +D3DVIEWPORT8 * +FLOAT * LPCVOID LPD3DXBUFFER * LPD3DXFONT * +LPD3DXMATRIXSTACK * LPDIRECT3DDEVICE8 %str -LPSTR +LPCSTR + +%wstr + +LPCWSTR + +%void + +void %%d3dxof.dll @@ -1360,6 +1406,7 @@ REFIID %long HRESULT +UINT %ptr @@ -1954,6 +2001,21 @@ LPSTR LPCWSTR LPWSTR +%%inetcomm.dll + +%long + +DWORD +HRESULT + +%ptr + +IMimeAllocator ** +IMimeMessage ** +IMimeSecurity ** +IStream ** +IUnknown * + %%inseng.dll %long @@ -4526,6 +4588,8 @@ LPCWSTR %long BOOL +CONFIGRET +DEVINST DI_FUNCTION DWORD HANDLE @@ -4534,6 +4598,7 @@ HDSKSPC HINF HINSTANCE HKEY +HMACHINE HSPFILELOG HSPFILEQ HSTRING_TABLE @@ -4543,6 +4608,7 @@ LogSeverity LONG REGSAM UINT +ULONG %long --pointer @@ -4565,6 +4631,7 @@ LPWIN32_FIND_DATAW LPWSTR * PBYTE PDWORD +PHMACHINE PINFCONTEXT PINT PSECURITY_DESCRIPTOR @@ -4590,15 +4657,16 @@ PCSTR * PCWSTR * PSTR * PUINT +PULONG PVOID PWSTR * UINT * -void * %str LPCSTR LPSTR +PCHAR PCSTR PSTR @@ -5079,6 +5147,7 @@ pTW_IDENTITY BOOL DWORD +HINSTANCE HRESULT HWND int diff --git a/tools/wine.inf b/tools/wine.inf index c3cb89c72b4..312d66c5bef 100644 --- a/tools/wine.inf +++ b/tools/wine.inf @@ -206,7 +206,7 @@ HKCU,Software\Wine\Debug,"RelayFromExclude",2,"winex11.drv;user32;gdi32;advapi32 HKCU,%Desktop%,"FontSmoothing",2,"0" HKCU,%Desktop%,"DragFullWindows",2,"0" HKCU,%Desktop%,"SmoothScroll",3,00,00,00,00 -HKCU,%Desktop%,"UserPreferencemask",3,10,00,00,00 +HKCU,%Desktop%,"UserPreferenceMask",3,10,00,00,80 HKCU,%Desktop%,"LowPowerActive",,"0" [Metrics] diff --git a/tools/winedump/lnk.c b/tools/winedump/lnk.c index 529e4efd536..53d2a55cf30 100644 --- a/tools/winedump/lnk.c +++ b/tools/winedump/lnk.c @@ -38,16 +38,41 @@ #include "pshpack1.h" -#define SCF_PIDL 1 -#define SCF_LOCATION 2 -#define SCF_DESCRIPTION 4 -#define SCF_RELATIVE 8 -#define SCF_WORKDIR 0x10 -#define SCF_ARGS 0x20 -#define SCF_CUSTOMICON 0x40 -#define SCF_UNICODE 0x80 -#define SCF_PRODUCT 0x800 -#define SCF_COMPONENT 0x1000 +typedef enum { + SLDF_HAS_ID_LIST = 0x00000001, + SLDF_HAS_LINK_INFO = 0x00000002, + SLDF_HAS_NAME = 0x00000004, + SLDF_HAS_RELPATH = 0x00000008, + SLDF_HAS_WORKINGDIR = 0x00000010, + SLDF_HAS_ARGS = 0x00000020, + SLDF_HAS_ICONLOCATION = 0x00000040, + SLDF_UNICODE = 0x00000080, + SLDF_FORCE_NO_LINKINFO = 0x00000100, + SLDF_HAS_EXP_SZ = 0x00000200, + SLDF_RUN_IN_SEPARATE = 0x00000400, + SLDF_HAS_LOGO3ID = 0x00000800, + SLDF_HAS_DARWINID = 0x00001000, + SLDF_RUNAS_USER = 0x00002000, + SLDF_HAS_EXP_ICON_SZ = 0x00004000, + SLDF_NO_PIDL_ALIAS = 0x00008000, + SLDF_FORCE_UNCNAME = 0x00010000, + SLDF_RUN_WITH_SHIMLAYER = 0x00020000, + SLDF_FORCE_NO_LINKTRACK = 0x00040000, + SLDF_ENABLE_TARGET_METADATA = 0x00080000, + SLDF_DISABLE_KNOWNFOLDER_RELATIVE_TRACKING = 0x00200000, + SLDF_RESERVED = 0x80000000, +} SHELL_LINK_DATA_FLAGS; + +#define EXP_SZ_LINK_SIG 0xa0000001 +#define EXP_SPECIAL_FOLDER_SIG 0xa0000005 +#define EXP_DARWIN_ID_SIG 0xa0000006 +#define EXP_SZ_ICON_SIG 0xa0000007 + +typedef struct tagDATABLOCKHEADER +{ + DWORD cbSize; + DWORD dwSignature; +} DATABLOCK_HEADER; typedef struct _LINK_HEADER { @@ -66,13 +91,13 @@ typedef struct _LINK_HEADER DWORD Unknown6; /* 0x48 */ } LINK_HEADER, * PLINK_HEADER; -typedef struct tagLINK_ADVERTISEINFO +typedef struct tagLINK_SZ_BLOCK { DWORD size; DWORD magic; CHAR bufA[MAX_PATH]; WCHAR bufW[MAX_PATH]; -} LINK_ADVERTISEINFO; +} LINK_SZ_BLOCK; typedef struct _LOCATION_INFO { @@ -93,6 +118,14 @@ typedef struct _LOCAL_VOLUME_INFO DWORD dwVolLabelOfs; } LOCAL_VOLUME_INFO; +typedef struct +{ + DWORD cbSize; + DWORD dwSignature; + DWORD idSpecialFolder; + DWORD cbOffset; +} EXP_SPECIAL_FOLDER; + typedef struct lnk_string_tag { unsigned short size; @@ -265,57 +298,112 @@ static int base85_to_guid( const char *str, LPGUID guid ) return 1; } -static int dump_advertise_info(const char *type) +static int dump_special_folder_block(const DATABLOCK_HEADER* bhdr) +{ + const EXP_SPECIAL_FOLDER *sfb = (const EXP_SPECIAL_FOLDER*)bhdr; + printf("Special folder block\n"); + printf("--------------------\n\n"); + printf("folder = 0x%04x\n", sfb->idSpecialFolder); + printf("offset = %d\n", sfb->cbOffset); + printf("\n"); + return 0; +} + +static int dump_sz_block(const DATABLOCK_HEADER* bhdr, const char* label) { - const LINK_ADVERTISEINFO *avt; + const LINK_SZ_BLOCK *szp = (const LINK_SZ_BLOCK*)bhdr; + printf("String block\n"); + printf("-----------\n\n"); + printf("magic = %x\n", szp->magic); + printf("%s = %s\n", label, szp->bufA); + printf("\n"); + return 0; +} - avt = fetch_block(); - if (!avt) - return -1; +static int dump_darwin_id(const DATABLOCK_HEADER* bhdr) +{ + const LINK_SZ_BLOCK *szp = (const LINK_SZ_BLOCK*)bhdr; + char comp_str[40]; + const char *feat, *comp, *prod_str, *feat_str; + GUID guid; printf("Advertise Info\n"); printf("--------------\n\n"); - printf("magic = %x\n", avt->magic); - printf("%s = %s\n", type, avt->bufA); - if (avt->magic == 0xa0000006) - { - char comp_str[40]; - const char *feat, *comp, *prod_str, *feat_str; - GUID guid; - - if (base85_to_guid(avt->bufA, &guid)) - prod_str = get_guid_str( &guid ); - else - prod_str = "?"; - - comp = &avt->bufA[20]; - feat = strchr(comp,'>'); - if (!feat) - feat = strchr(comp,'<'); - if (feat) - { - memcpy( comp_str, comp, feat - comp ); - comp_str[feat-comp] = 0; - } - else - { - strcpy( comp_str, "?" ); - } + printf("msi string = %s\n", szp->bufA); - if (feat && feat[0] == '>' && base85_to_guid( &feat[1], &guid )) - feat_str = get_guid_str( &guid ); - else - feat_str = ""; + if (base85_to_guid(szp->bufA, &guid)) + prod_str = get_guid_str(&guid); + else + prod_str = "?"; - printf(" product: %s\n", prod_str); - printf(" component: %s\n", comp_str ); - printf(" feature: %s\n", feat_str); + comp = &szp->bufA[20]; + feat = strchr(comp, '>'); + if (!feat) + feat = strchr(comp, '<'); + if (feat) + { + memcpy(comp_str, comp, feat - comp); + comp_str[feat-comp] = 0; + } + else + { + strcpy(comp_str, "?"); } + + if (feat && feat[0] == '>' && base85_to_guid( &feat[1], &guid )) + feat_str = get_guid_str( &guid ); + else + feat_str = ""; + + printf(" product: %s\n", prod_str); + printf(" component: %s\n", comp_str ); + printf(" feature: %s\n", feat_str); printf("\n"); return 0; } +static int dump_raw_block(const DATABLOCK_HEADER* bhdr) +{ + int data_size; + + printf("Raw Block\n"); + printf("---------\n\n"); + printf("size = %d\n", bhdr->cbSize); + printf("magic = %x\n", bhdr->dwSignature); + + data_size=bhdr->cbSize-sizeof(*bhdr); + if (data_size > 0) + { + unsigned int i; + const unsigned char *data; + + printf("data = "); + data=(const unsigned char*)bhdr+sizeof(*bhdr); + while (data_size > 0) + { + for (i=0; i < 16; i++) + { + if (i < data_size) + printf("%02x ", data[i]); + else + printf(" "); + } + for (i=0; i < data_size && i < 16; i++) + printf("%c", (data[i] >= 32 && data[i] < 128 ? data[i] : '.')); + printf("\n"); + data_size-=16; + if (data_size <= 0) + break; + data+=16; + printf(" "); + } + } + printf("\n"); + + return 1; +} + static const GUID CLSID_ShellLink = {0x00021401L, 0, 0, {0xC0,0,0,0,0,0,0,0x46}}; enum FileSig get_kind_lnk(void) @@ -332,6 +420,8 @@ enum FileSig get_kind_lnk(void) void lnk_dump(void) { const LINK_HEADER* hdr; + const DATABLOCK_HEADER* bhdr; + DWORD dwFlags; offset = 0; hdr = fetch_block(); @@ -351,39 +441,82 @@ void lnk_dump(void) /* dump out all the flags */ printf("Flags: %04x ( ", hdr->dwFlags); -#define FLAG(x) if(hdr->dwFlags & SCF_##x) printf("%s ",#x); - FLAG(PIDL) - FLAG(LOCATION) - FLAG(DESCRIPTION) - FLAG(RELATIVE) - FLAG(WORKDIR) - FLAG(ARGS) - FLAG(CUSTOMICON) - FLAG(UNICODE) - FLAG(PRODUCT) - FLAG(COMPONENT) + dwFlags=hdr->dwFlags; +#define FLAG(x) do \ + { \ + if (dwFlags & SLDF_##x) \ + { \ + printf("%s ", #x); \ + dwFlags&=~SLDF_##x; \ + } \ + } while (0) + FLAG(HAS_ID_LIST); + FLAG(HAS_LINK_INFO); + FLAG(HAS_NAME); + FLAG(HAS_RELPATH); + FLAG(HAS_WORKINGDIR); + FLAG(HAS_ARGS); + FLAG(HAS_ICONLOCATION); + FLAG(UNICODE); + FLAG(FORCE_NO_LINKINFO); + FLAG(HAS_EXP_SZ); + FLAG(RUN_IN_SEPARATE); + FLAG(HAS_LOGO3ID); + FLAG(HAS_DARWINID); + FLAG(RUNAS_USER); + FLAG(HAS_EXP_ICON_SZ); + FLAG(NO_PIDL_ALIAS); + FLAG(FORCE_UNCNAME); + FLAG(RUN_WITH_SHIMLAYER); + FLAG(FORCE_NO_LINKTRACK); + FLAG(ENABLE_TARGET_METADATA); + FLAG(DISABLE_KNOWNFOLDER_RELATIVE_TRACKING); + FLAG(RESERVED); #undef FLAG + if (dwFlags) + printf("+%04x", dwFlags); printf(")\n"); printf("Length: %04x\n", hdr->dwFileLength); printf("\n"); - if (hdr->dwFlags & SCF_PIDL) + if (hdr->dwFlags & SLDF_HAS_ID_LIST) dump_pidl(); - if (hdr->dwFlags & SCF_LOCATION) + if (hdr->dwFlags & SLDF_HAS_LINK_INFO) dump_location(); - if (hdr->dwFlags & SCF_DESCRIPTION) - dump_string("Description", hdr->dwFlags & SCF_UNICODE); - if (hdr->dwFlags & SCF_RELATIVE) - dump_string("Relative path", hdr->dwFlags & SCF_UNICODE); - if (hdr->dwFlags & SCF_WORKDIR) - dump_string("Working directory", hdr->dwFlags & SCF_UNICODE); - if (hdr->dwFlags & SCF_ARGS) - dump_string("Arguments", hdr->dwFlags & SCF_UNICODE); - if (hdr->dwFlags & SCF_CUSTOMICON) - dump_string("Icon path", hdr->dwFlags & SCF_UNICODE); - if (hdr->dwFlags & SCF_PRODUCT) - dump_advertise_info("product"); - if (hdr->dwFlags & SCF_COMPONENT) - dump_advertise_info("msi string"); + if (hdr->dwFlags & SLDF_HAS_NAME) + dump_string("Description", hdr->dwFlags & SLDF_UNICODE); + if (hdr->dwFlags & SLDF_HAS_RELPATH) + dump_string("Relative path", hdr->dwFlags & SLDF_UNICODE); + if (hdr->dwFlags & SLDF_HAS_WORKINGDIR) + dump_string("Working directory", hdr->dwFlags & SLDF_UNICODE); + if (hdr->dwFlags & SLDF_HAS_ARGS) + dump_string("Arguments", hdr->dwFlags & SLDF_UNICODE); + if (hdr->dwFlags & SLDF_HAS_ICONLOCATION) + dump_string("Icon path", hdr->dwFlags & SLDF_UNICODE); + + bhdr=fetch_block(); + while (bhdr) + { + if (!bhdr->cbSize) + break; + switch (bhdr->dwSignature) + { + case EXP_SZ_LINK_SIG: + dump_sz_block(bhdr, "exp.link"); + break; + case EXP_SPECIAL_FOLDER_SIG: + dump_special_folder_block(bhdr); + break; + case EXP_SZ_ICON_SIG: + dump_sz_block(bhdr, "icon"); + break; + case EXP_DARWIN_ID_SIG: + dump_darwin_id(bhdr); + break; + default: + dump_raw_block(bhdr); + } + bhdr=fetch_block(); + } } diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c index 42878f23f2e..7fb77c45b4e 100644 --- a/tools/winedump/msc.c +++ b/tools/winedump/msc.c @@ -992,6 +992,12 @@ int codeview_dump_symbols(const void* root, unsigned long size) sym->stack_v3.symtype, curr_func); break; + case S_BPREL_XXXX_V3: + printf("\tS-BP-relative XXXX V3: '%s' @%d type:%x unkn:%x (in %s)\n", + sym->stack_xxxx_v3.name, sym->stack_xxxx_v3.offset, + sym->stack_xxxx_v3.symtype, sym->stack_xxxx_v3.unknown, curr_func); + break; + case S_REGISTER_V1: printf("\tS-Register V1 '%s' in %s type:%x register:%x\n", p_string(&sym->register_v1.p_name), -- 2.11.4.GIT