From b8dcc2a6f0b5e8533bb6f2aa0ed36c425242734c Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Fri, 27 Jun 2008 18:12:47 +0200 Subject: [PATCH] push d2de4cbe4a771190295df18d4241bdf1a9d79e4b --- .gitignore | 11 + ANNOUNCE | 820 +++++++++++-- Make.rules.in | 1 + Makefile.in | 4 + VERSION | 2 +- configure | 242 +++- configure.ac | 46 +- dlls/Makefile.in | 2 + dlls/advapi32/advapi32.spec | 4 +- dlls/advapi32/security.c | 21 + dlls/advapi32/tests/lsa.c | 7 +- dlls/advpack/advpack.c | 4 +- dlls/avifil32/api.c | 2 +- dlls/comctl32/ipaddress.c | 9 + dlls/comctl32/listview.c | 60 +- dlls/comctl32/tooltips.c | 6 +- dlls/comdlg32/tests/filedlg.c | 31 +- dlls/d3d8/d3d8_main.c | 5 + dlls/d3d8/tests/visual.c | 30 +- dlls/d3d9/d3d9_main.c | 5 + dlls/d3d9/tests/d3d9ex.c | 3 + dlls/d3d9/tests/visual.c | 37 +- dlls/d3dx9_24/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_24/version.rc} | 16 +- dlls/d3dx9_25/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_25/version.rc} | 16 +- dlls/d3dx9_26/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_26/version.rc} | 16 +- dlls/d3dx9_27/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_27/version.rc} | 16 +- dlls/d3dx9_28/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_28/version.rc} | 16 +- dlls/d3dx9_29/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_29/version.rc} | 16 +- dlls/d3dx9_30/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_30/version.rc} | 16 +- dlls/d3dx9_31/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_31/version.rc} | 16 +- dlls/d3dx9_32/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_32/version.rc} | 16 +- dlls/d3dx9_33/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_33/version.rc} | 16 +- dlls/d3dx9_34/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_34/version.rc} | 16 +- dlls/d3dx9_35/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_35/version.rc} | 16 +- dlls/d3dx9_36/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_36/version.rc} | 16 +- dlls/d3dx9_37/Makefile.in | 2 + .../rpcss_np_client.h => d3dx9_37/version.rc} | 16 +- dlls/dbghelp/dbghelp.spec | 2 +- dlls/dbghelp/stabs.c | 2 +- dlls/dbghelp/symbol.c | 27 + dlls/ddraw/ddraw.c | 8 +- dlls/ddraw/ddraw_private.h | 6 +- dlls/ddraw/device.c | 1233 ++++++++++++++++++-- dlls/ddraw/direct3d.c | 6 +- dlls/ddraw/main.c | 38 +- dlls/devenum/mediacatenum.c | 5 +- dlls/dsound/dsound.c | 3 +- dlls/dsound/tests/dsound.c | 30 +- dlls/dxdiagn/provider.c | 122 +- dlls/gdi32/driver.c | 8 +- dlls/gdi32/font.c | 26 +- dlls/gdi32/freetype.c | 335 ++++-- dlls/gdi32/tests/font.c | 476 +++++++- dlls/gdiplus/font.c | 384 ++++++ dlls/gdiplus/gdiplus.spec | 50 +- dlls/gdiplus/gdiplus_private.h | 11 + dlls/gdiplus/graphics.c | 34 + dlls/gdiplus/graphicspath.c | 95 +- dlls/gdiplus/image.c | 13 + dlls/gdiplus/imageattributes.c | 11 + dlls/gdiplus/pathiterator.c | 10 + dlls/gdiplus/pen.c | 70 ++ dlls/gdiplus/tests/font.c | 146 ++- dlls/gdiplus/tests/graphicspath.c | 57 +- dlls/gdiplus/tests/image.c | 27 + dlls/hhctrl.ocx/Ru.rc | 6 +- dlls/inetcomm/mimeole.c | 4 +- dlls/{d3dx9_26 => inetmib1}/Makefile.in | 7 +- dlls/inetmib1/inetmib1.spec | 4 + dlls/inetmib1/main.c | 1171 +++++++++++++++++++ dlls/{riched20 => inetmib1}/tests/Makefile.in | 6 +- dlls/inetmib1/tests/main.c | 366 ++++++ dlls/iphlpapi/ipstats.c | 393 ++++++- dlls/kernel32/console.c | 37 +- dlls/kernel32/kernel32.spec | 5 +- dlls/kernel32/nls/afk.nls | 1 + dlls/kernel32/nls/ara.nls | 1 + dlls/kernel32/nls/arb.nls | 1 + dlls/kernel32/nls/are.nls | 1 + dlls/kernel32/nls/arg.nls | 1 + dlls/kernel32/nls/arh.nls | 1 + dlls/kernel32/nls/ari.nls | 1 + dlls/kernel32/nls/arj.nls | 1 + dlls/kernel32/nls/ark.nls | 1 + dlls/kernel32/nls/arl.nls | 1 + dlls/kernel32/nls/arm.nls | 1 + dlls/kernel32/nls/aro.nls | 1 + dlls/kernel32/nls/arq.nls | 1 + dlls/kernel32/nls/ars.nls | 1 + dlls/kernel32/nls/art.nls | 1 + dlls/kernel32/nls/aru.nls | 1 + dlls/kernel32/nls/ary.nls | 1 + dlls/kernel32/nls/aze.nls | 1 + dlls/kernel32/nls/azl.nls | 1 + dlls/kernel32/nls/bel.nls | 1 + dlls/kernel32/nls/bgr.nls | 1 + dlls/kernel32/nls/brf.nls | 1 + dlls/kernel32/nls/cat.nls | 1 + dlls/kernel32/nls/chs.nls | 1 + dlls/kernel32/nls/cht.nls | 1 + dlls/kernel32/nls/cor.nls | 1 + dlls/kernel32/nls/csy.nls | 1 + dlls/kernel32/nls/cym.nls | 1 + dlls/kernel32/nls/dan.nls | 1 + dlls/kernel32/nls/dea.nls | 1 + dlls/kernel32/nls/dec.nls | 1 + dlls/kernel32/nls/del.nls | 1 + dlls/kernel32/nls/des.nls | 1 + dlls/kernel32/nls/deu.nls | 1 + dlls/kernel32/nls/div.nls | 1 + dlls/kernel32/nls/ell.nls | 1 + dlls/kernel32/nls/ena.nls | 1 + dlls/kernel32/nls/enb.nls | 1 + dlls/kernel32/nls/enc.nls | 1 + dlls/kernel32/nls/eng.nls | 1 + dlls/kernel32/nls/eni.nls | 1 + dlls/kernel32/nls/enj.nls | 1 + dlls/kernel32/nls/enl.nls | 1 + dlls/kernel32/nls/enp.nls | 1 + dlls/kernel32/nls/ens.nls | 1 + dlls/kernel32/nls/ent.nls | 1 + dlls/kernel32/nls/enu.nls | 1 + dlls/kernel32/nls/enw.nls | 1 + dlls/kernel32/nls/enz.nls | 1 + dlls/kernel32/nls/eox.nls | 14 +- dlls/kernel32/nls/esa.nls | 1 + dlls/kernel32/nls/esb.nls | 1 + dlls/kernel32/nls/esc.nls | 1 + dlls/kernel32/nls/esd.nls | 1 + dlls/kernel32/nls/ese.nls | 1 + dlls/kernel32/nls/esf.nls | 1 + dlls/kernel32/nls/esg.nls | 1 + dlls/kernel32/nls/esh.nls | 1 + dlls/kernel32/nls/esi.nls | 1 + dlls/kernel32/nls/esl.nls | 1 + dlls/kernel32/nls/esm.nls | 1 + dlls/kernel32/nls/esn.nls | 1 + dlls/kernel32/nls/eso.nls | 1 + dlls/kernel32/nls/esp.nls | 1 + dlls/kernel32/nls/esr.nls | 1 + dlls/kernel32/nls/ess.nls | 1 + dlls/kernel32/nls/esu.nls | 1 + dlls/kernel32/nls/esv.nls | 1 + dlls/kernel32/nls/esy.nls | 1 + dlls/kernel32/nls/esz.nls | 1 + dlls/kernel32/nls/eti.nls | 1 + dlls/kernel32/nls/euq.nls | 1 + dlls/kernel32/nls/far.nls | 1 + dlls/kernel32/nls/fin.nls | 1 + dlls/kernel32/nls/fos.nls | 1 + dlls/kernel32/nls/fra.nls | 1 + dlls/kernel32/nls/frb.nls | 1 + dlls/kernel32/nls/frc.nls | 1 + dlls/kernel32/nls/frl.nls | 1 + dlls/kernel32/nls/frm.nls | 1 + dlls/kernel32/nls/frs.nls | 1 + dlls/kernel32/nls/gae.nls | 1 + dlls/kernel32/nls/gdh.nls | 1 + dlls/kernel32/nls/gdv.nls | 1 + dlls/kernel32/nls/glc.nls | 1 + dlls/kernel32/nls/guj.nls | 1 + dlls/kernel32/nls/heb.nls | 1 + dlls/kernel32/nls/hin.nls | 1 + dlls/kernel32/nls/hrv.nls | 1 + dlls/kernel32/nls/hun.nls | 1 + dlls/kernel32/nls/hye.nls | 1 + dlls/kernel32/nls/ind.nls | 1 + dlls/kernel32/nls/isl.nls | 1 + dlls/kernel32/nls/ita.nls | 1 + dlls/kernel32/nls/its.nls | 1 + dlls/kernel32/nls/jpn.nls | 1 + dlls/kernel32/nls/kan.nls | 1 + dlls/kernel32/nls/kat.nls | 1 + dlls/kernel32/nls/kkz.nls | 1 + dlls/kernel32/nls/knk.nls | 1 + dlls/kernel32/nls/kor.nls | 1 + dlls/kernel32/nls/kyr.nls | 1 + dlls/kernel32/nls/lth.nls | 1 + dlls/kernel32/nls/lvi.nls | 1 + dlls/kernel32/nls/mar.nls | 1 + dlls/kernel32/nls/mki.nls | 1 + dlls/kernel32/nls/mon.nls | 1 + dlls/kernel32/nls/msb.nls | 1 + dlls/kernel32/nls/msl.nls | 1 + dlls/kernel32/nls/nlb.nls | 1 + dlls/kernel32/nls/nld.nls | 1 + dlls/kernel32/nls/nls.nls | 1 + dlls/kernel32/nls/non.nls | 1 + dlls/kernel32/nls/nor.nls | 1 + dlls/kernel32/nls/pan.nls | 1 + dlls/kernel32/nls/plk.nls | 1 + dlls/kernel32/nls/ptb.nls | 1 + dlls/kernel32/nls/ptg.nls | 1 + dlls/kernel32/nls/rmc.nls | 1 + dlls/kernel32/nls/rom.nls | 1 + dlls/kernel32/nls/rus.nls | 1 + dlls/kernel32/nls/san.nls | 1 + dlls/kernel32/nls/sky.nls | 1 + dlls/kernel32/nls/slv.nls | 1 + dlls/kernel32/nls/sqi.nls | 1 + dlls/kernel32/nls/srb.nls | 1 + dlls/kernel32/nls/srl.nls | 1 + dlls/kernel32/nls/sve.nls | 1 + dlls/kernel32/nls/svf.nls | 1 + dlls/kernel32/nls/swk.nls | 1 + dlls/kernel32/nls/syr.nls | 1 + dlls/kernel32/nls/tam.nls | 1 + dlls/kernel32/nls/tel.nls | 1 + dlls/kernel32/nls/tha.nls | 1 + dlls/kernel32/nls/trk.nls | 1 + dlls/kernel32/nls/ttt.nls | 1 + dlls/kernel32/nls/ukr.nls | 1 + dlls/kernel32/nls/urd.nls | 1 + dlls/kernel32/nls/uzb.nls | 1 + dlls/kernel32/nls/uzl.nls | 1 + dlls/kernel32/nls/vit.nls | 1 + dlls/kernel32/nls/wal.nls | 1 + dlls/kernel32/nls/zhh.nls | 1 + dlls/kernel32/nls/zhi.nls | 1 + dlls/kernel32/nls/zhm.nls | 1 + dlls/kernel32/sync.c | 27 +- dlls/kernel32/tests/console.c | 45 + dlls/kernel32/tests/debugger.c | 4 + dlls/kernel32/tests/thread.c | 228 ++++ dlls/localspl/tests/localmon.c | 1 + dlls/mapi32/tests/prop.c | 44 +- dlls/mciavi32/mmoutput.c | 19 +- dlls/mpr/wnet.c | 2 + dlls/mscms/tests/profile.c | 2 +- dlls/mshtml/htmldoc3.c | 27 +- dlls/mshtml/htmlelem.c | 91 +- dlls/mshtml/htmlelem2.c | 42 +- dlls/mshtml/htmlevent.c | 68 +- dlls/mshtml/htmlimg.c | 24 +- dlls/mshtml/htmlinput.c | 11 +- dlls/mshtml/htmlnode.c | 187 ++- dlls/mshtml/htmlselect.c | 63 +- dlls/mshtml/mshtml_private.h | 19 +- dlls/mshtml/nsembed.c | 7 +- dlls/mshtml/nsevents.c | 61 + dlls/mshtml/nsiface.idl | 33 + dlls/mshtml/nsio.c | 5 +- dlls/mshtml/tests/dom.c | 413 ++++++- dlls/mshtml/txtrange.c | 2 + dlls/msi/action.c | 392 ++++--- dlls/msi/files.c | 50 +- dlls/msi/msi.c | 126 +- dlls/msi/msipriv.h | 4 + dlls/msi/registry.c | 96 ++ dlls/msi/tests/automation.c | 16 +- dlls/msi/tests/install.c | 111 +- dlls/msi/tests/msi.c | 766 +++++++++++- dlls/msxml3/factory.c | 3 +- dlls/msxml3/tests/xmlelem.c | 4 +- dlls/netapi32/tests/access.c | 37 +- dlls/netapi32/tests/apibuf.c | 3 - dlls/ntdll/critsection.c | 52 +- dlls/ntdll/loader.c | 6 +- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/tests/rtlstr.c | 78 ++ dlls/ntdll/virtual.c | 15 + dlls/ole32/compobj.c | 6 +- dlls/ole32/enumx.c | 7 +- dlls/ole32/ole32_main.c | 1 + dlls/ole32/oleobj.c | 2 + dlls/ole32/stg_bigblockfile.c | 11 - dlls/oleaut32/tests/typelib.c | 2 +- dlls/quartz/avidec.c | 46 +- dlls/quartz/dsoundrender.c | 20 +- dlls/quartz/enumregfilters.c | 7 +- dlls/quartz/filtergraph.c | 826 ++++++++----- dlls/quartz/filtermapper.c | 7 +- dlls/quartz/memallocator.c | 184 +-- dlls/quartz/nullrenderer.c | 17 +- dlls/quartz/parser.c | 33 +- dlls/quartz/pin.c | 155 +-- dlls/quartz/pin.h | 6 +- dlls/quartz/quartz_private.h | 46 + dlls/quartz/tests/videorenderer.c | 4 +- dlls/quartz/transform.c | 2 +- dlls/quartz/videorenderer.c | 144 ++- dlls/quartz/waveparser.c | 2 +- dlls/riched20/caret.c | 41 +- dlls/riched20/editor.c | 63 +- dlls/riched20/editor.h | 10 +- dlls/riched20/editstr.h | 3 +- dlls/riched20/list.c | 1 + dlls/riched20/paint.c | 9 +- dlls/riched20/para.c | 5 +- dlls/riched20/reader.c | 12 +- dlls/riched20/richole.c | 1001 +++++++++++++++- dlls/riched20/run.c | 7 +- dlls/riched20/string.c | 18 +- dlls/riched20/style.c | 9 + dlls/riched20/tests/Makefile.in | 5 +- dlls/riched20/tests/editor.c | 423 ++++++- dlls/riched20/tests/richole.c | 120 ++ dlls/riched20/undo.c | 118 +- dlls/riched20/wrap.c | 51 +- dlls/riched32/richedit.c | 2 +- dlls/riched32/tests/editor.c | 125 ++ dlls/rpcrt4/Makefile.in | 6 +- dlls/rpcrt4/{rpcss_np_client.h => epm.idl} | 11 +- dlls/rpcrt4/epm_towers.h | 6 +- dlls/rpcrt4/ndr_clientserver.c | 17 +- dlls/rpcrt4/ndr_marshall.c | 193 +-- dlls/rpcrt4/rpc_binding.c | 21 +- dlls/rpcrt4/rpc_binding.h | 3 - dlls/rpcrt4/rpc_epmap.c | 453 +++++-- dlls/rpcrt4/rpcrt4.spec | 2 +- dlls/rpcrt4/rpcrt4_main.c | 108 -- dlls/rpcrt4/rpcss_np_client.c | 152 --- dlls/rpcrt4/tests/generated.c | 2 +- dlls/rpcrt4/tests/ndr_marshall.c | 38 +- dlls/rpcrt4/tests/rpc.c | 51 + dlls/rpcrt4/tests/server.c | 33 +- dlls/rpcrt4/tests/server.idl | 9 + dlls/secur32/tests/schannel.c | 3 +- dlls/setupapi/tests/devinst.c | 210 ++-- dlls/setupapi/tests/install.c | 39 + dlls/shdocvw/webbrowser.c | 35 +- dlls/shell32/control.c | 105 +- dlls/shell32/cpanelfolder.c | 11 +- dlls/shell32/iconcache.c | 25 + dlls/shell32/regsvr.c | 30 +- dlls/shell32/shell32.spec | 4 +- dlls/shell32/shell32_Bg.rc | 1 + dlls/shell32/shell32_Cs.rc | 1 + dlls/shell32/shell32_Da.rc | 1 + dlls/shell32/shell32_De.rc | 1 + dlls/shell32/shell32_En.rc | 1 + dlls/shell32/shell32_Eo.rc | 1 + dlls/shell32/shell32_Es.rc | 1 + dlls/shell32/shell32_Fi.rc | 1 + dlls/shell32/shell32_Fr.rc | 1 + dlls/shell32/shell32_It.rc | 1 + dlls/shell32/shell32_Ja.rc | 1 + dlls/shell32/shell32_Ko.rc | 1 + dlls/shell32/shell32_Nl.rc | 1 + dlls/shell32/shell32_No.rc | 1 + dlls/shell32/shell32_Pl.rc | 1 + dlls/shell32/shell32_Pt.rc | 1 + dlls/shell32/shell32_Ro.rc | 1 + dlls/shell32/shell32_Ru.rc | 1 + dlls/shell32/shell32_Si.rc | 1 + dlls/shell32/shell32_Tr.rc | 1 + dlls/shell32/shell32_Uk.rc | 1 + dlls/shell32/shresdef.h | 15 +- dlls/shell32/tests/Makefile.in | 2 +- dlls/shell32/tests/shelllink.c | 2 +- dlls/shell32/tests/shellpath.c | 32 +- .../tests/{shfldr_netplaces.c => shfldr_special.c} | 34 +- dlls/shell32/tests/shlfolder.c | 32 +- dlls/shlwapi/string.c | 6 +- dlls/shlwapi/tests/path.c | 14 +- dlls/shlwapi/tests/url.c | 4 + dlls/shlwapi/url.c | 7 + dlls/strmiids/strmiids.c | 3 + dlls/urlmon/file.c | 11 +- dlls/urlmon/tests/protocol.c | 10 +- dlls/user32/class.c | 1 + dlls/user32/controls.h | 1 + dlls/user32/dde_client.c | 4 +- dlls/user32/dialog.c | 2 +- dlls/user32/focus.c | 1 + dlls/user32/menu.c | 6 +- dlls/user32/message.c | 39 +- dlls/user32/sysparams.c | 38 +- dlls/user32/tests/msg.c | 221 +++- dlls/user32/tests/sysparams.c | 78 ++ dlls/user32/tests/win.c | 115 +- dlls/user32/user_main.c | 9 +- dlls/user32/user_private.h | 5 +- dlls/user32/win.c | 130 ++- dlls/user32/win.h | 2 + dlls/user32/winpos.c | 3 +- dlls/user32/winstation.c | 7 +- dlls/winealsa.drv/mixer.c | 2 +- dlls/wined3d/device.c | 4 + dlls/wined3d/directx.c | 37 +- dlls/wined3d/drawprim.c | 1 + dlls/wined3d/glsl_shader.c | 4 +- dlls/wined3d/utils.c | 2 +- dlls/wineps.drv/init.c | 12 +- dlls/winex11.drv/bitblt.c | 4 +- dlls/winex11.drv/clipboard.c | 169 ++- dlls/winex11.drv/desktop.c | 2 +- dlls/winex11.drv/event.c | 14 +- dlls/winex11.drv/keyboard.c | 13 +- dlls/winex11.drv/mouse.c | 6 +- dlls/winex11.drv/opengl.c | 256 ++-- dlls/winex11.drv/systray.c | 10 +- dlls/winex11.drv/window.c | 61 +- dlls/winex11.drv/wintab.c | 4 +- dlls/winex11.drv/x11ddraw.c | 7 +- dlls/winex11.drv/x11drv.h | 18 +- dlls/winex11.drv/x11drv_main.c | 4 +- dlls/winex11.drv/xim.c | 22 +- dlls/wininet/http.c | 25 +- dlls/wininet/internet.c | 40 +- dlls/wininet/tests/http.c | 20 +- dlls/wininet/tests/url.c | 27 + dlls/winmm/tests/mixer.c | 2 + dlls/winmm/tests/mmio.c | 31 +- dlls/winspool.drv/info.c | 24 +- dlls/ws2_32/socket.c | 12 +- dlls/ws2_32/tests/sock.c | 106 +- include/Makefile.in | 3 + include/axcore.idl | 4 + include/config.h.in | 24 + include/control.idl | 10 +- include/dbt.h | 2 + include/dsound.h | 2 +- include/gdiplusenums.h | 11 + include/gdiplusflat.h | 27 + include/gdiplusgpstubs.h | 4 + include/iprtrmib.h | 4 + include/msinkaut.idl | 376 +++++- include/ole2.h | 3 + include/richedit.h | 394 ++++++- include/rpcdce.h | 5 + include/rpcndr.h | 11 +- include/shobjidl.idl | 6 +- include/uuids.h | 1 + include/vmr9.idl | 525 +++++++++ include/winbase.h | 3 + include/wine/dcetypes.idl | 88 ++ include/wine/epm.idl | 122 ++ include/wine/server_protocol.h | 5 +- include/wine/wined3d_types.h | 4 +- include/winnt.h | 6 + include/winternl.h | 3 +- include/xmldom.idl | 72 ++ include/xmldomdid.h | 15 + programs/explorer/desktop.c | 10 +- programs/oleview/Ru.rc | 213 ++++ programs/oleview/rsrc.rc | 1 + programs/regedit/edit.c | 8 +- programs/rpcss/Makefile.in | 8 +- .../rpcss_np_client.h => programs/rpcss/epm.idl | 11 +- programs/rpcss/epmap_server.c | 210 ---- programs/rpcss/epmp.c | 283 +++++ programs/rpcss/np_server.c | 527 --------- programs/rpcss/rpcss.h | 22 - programs/rpcss/rpcss_main.c | 94 +- programs/taskmgr/Ru.rc | 500 ++++++++ programs/taskmgr/taskmgr.rc | 1 + programs/winecfg/Bg.rc | 5 + programs/winecfg/Cs.rc | 5 + programs/winecfg/Da.rc | 5 + programs/winecfg/De.rc | 5 + programs/winecfg/En.rc | 5 + programs/winecfg/Es.rc | 5 + programs/winecfg/Fi.rc | 5 + programs/winecfg/Fr.rc | 5 + programs/winecfg/Hu.rc | 5 + programs/winecfg/It.rc | 5 + programs/winecfg/Ja.rc | 5 + programs/winecfg/Ko.rc | 5 + programs/winecfg/Nl.rc | 5 + programs/winecfg/No.rc | 5 + programs/winecfg/Pl.rc | 5 + programs/winecfg/Pt.rc | 10 + programs/winecfg/Ro.rc | 5 + programs/winecfg/Ru.rc | 5 + programs/winecfg/Si.rc | 5 + programs/winecfg/Sv.rc | 5 + programs/winecfg/Tr.rc | 5 + programs/winecfg/Zh.rc | 5 + programs/winecfg/main.c | 57 +- programs/winecfg/resource.h | 4 + programs/winedbg/tgt_active.c | 4 +- programs/winemine/README | 3 - programs/winemine/main.c | 60 +- programs/winemine/main.h | 10 +- programs/winetest/Makefile.in | 3 + programs/winetest/winetest.rc | 1 + programs/winhlp32/Bg.rc | 17 +- programs/winhlp32/Cs.rc | 17 +- programs/winhlp32/Da.rc | 17 +- programs/winhlp32/De.rc | 17 +- programs/winhlp32/En.rc | 17 +- programs/winhlp32/Eo.rc | 17 +- programs/winhlp32/Es.rc | 17 +- programs/winhlp32/Fi.rc | 17 +- programs/winhlp32/Fr.rc | 17 +- programs/winhlp32/Hu.rc | 17 +- programs/winhlp32/It.rc | 17 +- programs/winhlp32/Ko.rc | 17 +- programs/winhlp32/Nl.rc | 17 +- programs/winhlp32/No.rc | 17 +- programs/winhlp32/Pl.rc | 17 +- programs/winhlp32/Pt.rc | 34 +- programs/winhlp32/Rm.rc | 17 +- programs/winhlp32/Ru.rc | 17 +- programs/winhlp32/Si.rc | 19 +- programs/winhlp32/Sk.rc | 17 +- programs/winhlp32/Sv.rc | 17 +- programs/winhlp32/Tr.rc | 17 +- programs/winhlp32/Wa.rc | 17 +- programs/winhlp32/Zh.rc | 17 +- programs/winhlp32/winhelp.c | 30 +- programs/winhlp32/winhelp_res.h | 18 +- programs/wordpad/wordpad.c | 4 +- server/atom.c | 64 +- server/class.c | 19 +- server/object.h | 4 +- server/process.c | 27 +- server/protocol.def | 3 +- server/trace.c | 3 +- server/user.h | 2 + server/window.c | 209 ++-- server/winstation.c | 2 + tools/c2man.pl | 8 +- tools/widl/parser.y | 47 +- tools/widl/typegen.c | 178 ++- tools/wine.desktop | 24 +- tools/wine.inf.in | 14 +- tools/winegcc/Makefile.in | 1 + tools/winegcc/winegcc.c | 2 + 534 files changed, 17858 insertions(+), 4197 deletions(-) rewrite ANNOUNCE (71%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_24/version.rc} (70%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_25/version.rc} (70%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_26/version.rc} (70%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_27/version.rc} (70%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_28/version.rc} (70%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_29/version.rc} (70%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_30/version.rc} (70%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_31/version.rc} (70%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_32/version.rc} (70%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_33/version.rc} (70%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_34/version.rc} (70%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_35/version.rc} (69%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_36/version.rc} (69%) copy dlls/{rpcrt4/rpcss_np_client.h => d3dx9_37/version.rc} (69%) copy dlls/{d3dx9_26 => inetmib1}/Makefile.in (68%) create mode 100644 dlls/inetmib1/inetmib1.spec create mode 100644 dlls/inetmib1/main.c copy dlls/{riched20 => inetmib1}/tests/Makefile.in (72%) create mode 100644 dlls/inetmib1/tests/main.c create mode 100644 dlls/riched20/tests/richole.c copy dlls/rpcrt4/{rpcss_np_client.h => epm.idl} (73%) delete mode 100644 dlls/rpcrt4/rpcss_np_client.c rename dlls/shell32/tests/{shfldr_netplaces.c => shfldr_special.c} (60%) create mode 100644 include/vmr9.idl create mode 100644 include/wine/dcetypes.idl create mode 100644 include/wine/epm.idl create mode 100644 programs/oleview/Ru.rc rename dlls/rpcrt4/rpcss_np_client.h => programs/rpcss/epm.idl (73%) delete mode 100644 programs/rpcss/epmap_server.c create mode 100644 programs/rpcss/epmp.c delete mode 100644 programs/rpcss/np_server.c create mode 100644 programs/taskmgr/Ru.rc diff --git a/.gitignore b/.gitignore index 9d9d24de1d7..75698d9ef98 100644 --- a/.gitignore +++ b/.gitignore @@ -158,6 +158,9 @@ dlls/inetcomm/libinetcomm.def dlls/inetcomm/tests/*.ok dlls/inetcomm/tests/inetcomm_crosstest.exe dlls/inetcomm/tests/testlist.c +dlls/inetmib1/tests/*.ok +dlls/inetmib1/tests/inetmib1_crosstest.exe +dlls/inetmib1/tests/testlist.c dlls/infosoft/tests/*.ok dlls/infosoft/tests/infosoft_crosstest.exe dlls/infosoft/tests/testlist.c @@ -343,6 +346,8 @@ dlls/riched20/tests/testlist.c dlls/riched32/tests/*.ok dlls/riched32/tests/riched32_crosstest.exe dlls/riched32/tests/testlist.c +dlls/rpcrt4/epm.h +dlls/rpcrt4/epm_c.c dlls/rpcrt4/librpcrt4.def dlls/rpcrt4/tests/*.ok dlls/rpcrt4/tests/rpcrt4_crosstest.exe @@ -545,6 +550,9 @@ include/tom.h include/unknwn.h include/urlhist.h include/urlmon.h +include/vmr9.h +include/wine/dcetypes.h +include/wine/epm.h include/wine/itss.h include/wine/svcctl.h include/wtypes.h @@ -586,6 +594,8 @@ programs/progman/progman programs/reg/reg programs/regedit/regedit programs/regsvr32/regsvr32 +programs/rpcss/epm.h +programs/rpcss/epm_s.c programs/rpcss/irot.h programs/rpcss/irot_s.c programs/rpcss/rpcss @@ -641,6 +651,7 @@ programs/winetest/gdiplus_test.exe programs/winetest/hlink_test.exe programs/winetest/imm32_test.exe programs/winetest/inetcomm_test.exe +programs/winetest/inetmib1_test.exe programs/winetest/infosoft_test.exe programs/winetest/iphlpapi_test.exe programs/winetest/itss_test.exe diff --git a/ANNOUNCE b/ANNOUNCE dissimilarity index 71% index 3809c2ee883..a8af44b7b3d 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,72 +1,748 @@ -The Wine team is proud to announce that Wine 1.0 is now available. -This is the first stable release of Wine after 15 years of development -and beta testing. Many thanks to everybody who helped us along that -long road! - -While compatibility is not perfect yet, thousands of applications have -been reported to work very well. Check http://appdb.winehq.org to see -the details for your favorite applications. - -The source is available from the following locations: - - http://ibiblio.org/pub/linux/system/emulators/wine/wine-1.0.tar.bz2 - http://prdownloads.sourceforge.net/wine/wine-1.0.tar.bz2 - -Binary packages for various distributions will be available from: - - http://www.winehq.org/site/download - -You will find documentation on http://www.winehq.org/site/documentation - -You can also get the current source directly from the git -repository. Check http://www.winehq.org/site/git for details. - -Wine is available thanks to the work of many people. See the file -AUTHORS in the distribution for the complete list. - ----------------------------------------------------------------- - -Bugs fixed in 1.0: - - 3838 The Punisher demo crashes after the introduction movies - 3898 Counter-Strike 1.6 performance issue - 4755 X Error of failed request: BadDrawable (X_PolyFillRectangle) when switching to Virtual Desktop - 6315 Starlancer draws ships as white when direct3d is enabled - 7268 Oni not opening after install - 8185 can't login in Skype 3.1 on wine/kubuntu 7 - 8634 antialiasing disabled in gtasa menu - 9555 Wine crash when I click help in Stata 10 - 9589 Static / Scratchy Sound with OSS in Call of Duty - 9903 WinRAR with NXServer - black icons - 10009 QIP: window z-order is still wrong - 10268 Robot Wars: Arena of Destruction crashes while quitting (causing resolution to stay 640 x 480) - 10322 Eve-online (video memory misaddressed?) - 10700 Dragon Naturally Speaking 9 needs gdiplus.GdipDrawArcI, gdiplus.GdipCreatePen2, ... - 11011 Call of Duty 1.0 doesn't run after install. - 11104 Dance Praise 2: Does not respond to input - 12415 Can not leave fullscreen Warcraft 3x (Regression) - 12963 Moto Racer 2 works with wine 0.9.60 and crashes with wine 0.9.61 - 13271 The demo of the punisher fails to install - 13740 winebrowser gets wrong URL, problem with unicode - ----------------------------------------------------------------- - -Changes since 1.0-rc5: - -Alexandre Julliard (1): - Updated the authors list. - -Francois Gouget (3): - Remove spaces before '...' in the Danish resources. - regedit: Remove spaces before '...'. - winecfg: Remove spaces before '...'. - -Jaime Rave (1): - wineconsole: Update Spanish translation. - -Matthias Kupfer (1): - wordpad: Small typo fix for German translation. - --- -Alexandre Julliard -julliard@winehq.org +The Wine development release 1.1.0 is now available. + +What's new in this release (see below for details): + - Many more gdiplus functions implemented. + - Improved graphics tablet support. + - Many Richedit fixes and improvements. + - Support for HWND_MESSAGE windows. + - A lot of new MSHTML functions. + - Many fixes in MSI registry handling. + - Initial implementation of the inetmib1 DLL. + - Improvements to the quartz renderers. + - Various bug fixes. + +The source is available from the following locations: + + http://ibiblio.org/pub/linux/system/emulators/wine/wine-1.0.tar.bz2 + http://prdownloads.sourceforge.net/wine/wine-1.0.tar.bz2 + +Binary packages for various distributions will be available from: + + http://www.winehq.org/site/download + +You will find documentation on http://www.winehq.org/site/documentation + +You can also get the current source directly from the git +repository. Check http://www.winehq.org/site/git for details. + +Wine is available thanks to the work of many people. See the file +AUTHORS in the distribution for the complete list. + +---------------------------------------------------------------- + +Bugs fixed in 1.1.0: + + 2918 Electronics Workbench: instruments are not drawn + 3159 Incorrect defintions of CFSTR_* + 3795 c2man: extension is fixed to ".dll" + 4437 Weird Worlds demo won't start without native msvcrt + 4935 IHP Kitchen: Unhandled page fault on read access + 5915 Application gets crashed when I press enter in combobox (While Cursor is present in combo) + 5986 riched20 : Double Click messages not handled + 6247 Richedit: Selecting via mouse does not scroll + 6618 Warcraft III Crash on intro movie playback + 7069 starting win32-version of tomcat fails with a "jvm_bind" or "java.util.TimeZone.getTimeZone" error message + 8132 Hyperlink rendering not turned off if link is at end of line + 8556 Game complains that directx9.0c is not installed + 8657 Ikea Home Planner crashes when I add an element + 8901 Personal Stock Monitor 6 standard Active Securities listview columns blank + 9812 Bad some czech characters in older coursewares + 9824 GTA Vice City: strange textures when you attack cars with a chainsaw + 9860 MSN 8.1 doesn't start, gdiplus:GdipImageGetFrameDimensionsList not implemented + 9924 SysIPAddress32 dialog item glitch + 9982 Dragon NaturallySpeaking training module - text is too big. + 10132 bad cyrillic font rendering + 10550 turbocad install won't work + 10966 explorer.exe crash every time when removing folders + 11158 Wineboot and virtual desktop + 11245 Tomb Raider Anniversary crash during trying to enable an usb joypad. + 11476 UMDGen "Compression Level" Dialog box doesn't show + 11699 Acecad tablet not recognised as a tablet + 11721 GL Excess does not work + 11774 eMule crashes when right-clicking on file in Transfers window + 12005 Regression in pressure sensitivity with wizardpen tablet driver and Photoshop 7 + 12167 MS Office 2000 install broken at 0.9.55 --> 0.9.56 + 12305 Firefox 3 beta 4 font problem: colon displayed as 0038 unicode glyph-missing glyph [dogfood] + 12481 PSPad HTML preview is not working with Gecko + 12631 FIFA 2007 - black rectangles during gameplay in the recent version + 12740 Wine tries to execute non-executable data (regression against 0.9.59) + 13004 3Com Descovery Util do not see any network interfaces + 13036 Faktury 4.1 doesn't run because of Unimplemented GdipImageGetFrameDimensionsCount + 13122 Graphical regression in Team Fortress 2. + 13127 Star wars JK II Jedi outcast does not work + 13128 Medieval total war crashes + 13145 Graphic Corruption in Assassin's Creed + 13225 Sacrifice: texture transparency problems (alpha test) + 13227 100% CPU Usage with notepad - with dtrace output + 13341 Painkiller Demo Fails To Run + 13482 Latest msvcrt's won't load + 13513 Portal: game crashes + 13521 liveusb-creator-2.5 unable to load win32file.pyd [dogfood] + 13552 eDrawings CAD Viewer crashes into shell32 while opening a file + 13644 Ricochet Infinity cannot activate full version + 13713 Hema Album Software Advanced won't start, it crashes and has to be killed. + 13748 Last Chaos aborts after clicking 'start' in 0.9.57 and later + 13765 ZENcast 2.01.01 Installer Fails to Start + 13864 F.E.A.R: Can't accept EULA + 13882 psiops crashes while starting (XStreamlok) + 13892 mmioOpen MMIO_ALLOCBUF not ignored when passed a buffer + 13969 Photocameras Adjustment Software: crashes after pressing a button. + 14006 at least one locale missing: eo - (breaks .NET internationalization) + 14016 Eclipse 3.3.x (customized) needs WebBrowser_GetIDsOfNames fleshed out + 14024 Photoshop CS2 installer crashes immediately + +---------------------------------------------------------------- + +Changes since 1.0: + +Adam Petaccia (10): + gdiplus: Implement GdipCreateFontFamilyFromName. + gdiplus: Implement GdipDeleteFontFamily. + gdiplus: Implement GdipGetFamilyName. + gdiplus: Implement GdipGetGeneric*. + gdiplus: Tests for FontFamily. + gdiplus: Tests for GetGeneric*. + gdiplus: Implement GdipCreateFont. + gdiplus: Implement GdipGetFontUnit. + gdiplus: Implement GdipGetFontSize. + gdiplus: Tests for new font functions. + +Albert Lee (1): + ws2_32: WS_getaddrinfo TRACE message can crash Wine. + +Alex Villacís Lasso (12): + richedit: Fix misreporting of match offset for EM_FINDTEXT and EM_FINDTEXTEX. + richedit: WM_SETTEXT must immediately autodetect URLs, without waiting for a WM_CHAR. + richedit: Add more tests for URL autodetection on WM_CHAR, make them pass under Wine. + richedit: Fix for the semantics of the flags for some effects reported by EM_GETCHARFORMAT. + richedit: Add tests for URL autodetection for EM_SETTEXTEX, make them pass under Wine. + richedit: Add tests for URL autodetection for EM_REPLACESEL, make them pass under Wine. + richedit: Insertion style must NOT be cleared unless selection actually changed. + richedit: Empty text should result in a scroll range of 0. Tests for this behavior. + richedit: When returning position through wParam pointer, EM_POSFROMCHAR must return 0 as LRESULT. + richedit: EM_POSFROMCHAR should take into account scrollbar position. With tests. + richedit: Revert patch that introduced a test that fails on all platforms. + richedit: Fix failing EM_GETCHARFORMAT test on all platforms. + +Alexander Dorofeyev (5): + ddraw: Implement FPU mode fixup in d3d7 device. + quartz: Fix accessing variant string. + quartz: Do not ignore current position in IEnumRegFiltersImpl_Next. + devenum: Update type when reading binary data to VT_EMPTY variant. + quartz: Prevent heap corruption if IPropertyBag_Read fails. + +Alexandre Julliard (36): + winex11: Check for matching pixel format in wglMakeCurrent. + winex11: Avoid erasing the window when changing the pixel format. + cabinet: Always use INT_PTR for handles. + kernel32: The first argument of GetBinaryType is a string. + server: Move the process pipe hangup handling into kill_process. + winex11: Only register an XIM callback if we can't open the XIM right away. + winspool: Don't print NULL pointers in traces. + shell32/tests: Use the original path if GetLongPathNameA fails. + winex11: Print more details on OpenGL load failure. Only print errors once. + d3d8: Make Direct3DCreate8 fail if we can't initialize wined3d. + d3d9: Make Direct3DCreate9 fail if we can't initialize wined3d. + d3d9/tests: Test for Direct3DCreate9 failure. + ole32: Don't consider RPC_S_UUID_LOCAL_ONLY an error in CoCreateGuid. + oleaut32/tests: Allow UuidCreate to return RPC_S_UUID_LOCAL_ONLY. + server: Use a unicode_str to represent atom names. + server: Add support for a top-level message parent window in parallel to the desktop window. + user32: Register the builtin 'Message' window class. + user32: Add support for a top-level message parent window in parallel to the desktop window. + server: Also return the top-level message window in the get_desktop_window request. + explorer.exe: Create the top-level message window along with the desktop window. + user32: Use the top-level message window as parent for HWND_MESSAGE windows. + user32: Treat the top-level message window as a desktop window. + user32/tests: Add some more tests for HWND_MESSAGE windows. + user32: Add support for finding HWND_MESSAGE windows in FindWindowEx. + user32: Make sure that IsWindowVisible returns FALSE for HWND_MESSAGE windows. + ole32: Make the apartment window a HWND_MESSAGE window. + wine.inf: Make the initial owner information empty. + winex11: Explicitly request creation of the per-thread data where necessary. + winex11: Pass the display as parameter to a few more functions instead of using thread_display(). + winex11: Get rid of the explicit colormap management. + winex11: Explicitly request creation of the thread display where necessary. + winex11: Don't create a win data structure for HWND_MESSAGE windows. + server: Fix a potential desktop reference leak. + widl: [default] is an allowed attribute for union fields. + ntdll: Force execute permission again on the stack after clearing it. + configure: Fix the netinet header checks for Mac OS and Solaris. + +Alistair Leslie-Hughes (6): + urlmon: Check pointer before use. + msxml3: Improved checking of failed case. + secur32: Fix crash under win98. + shell32: Stop crash when an error occurs. + mapi32: Skip tests on error. + msxml3: Added support for creating DOMFreeThreadedDocument. + +Anatoly Lyutin (3): + user32: Return at the end of processing (cmd == SW_HIDE). + user32/tests: Add two tests for ShowWindow(SW_RESTORE). + user32/tests:c Add msg tests for SetActiveWindow(). + +Andrew Talbot (12): + user32: Dangling pointer fix. + advpack: Constify some variables. + qmgr: Constify some variables. + shell32: Constify a variable. + setupapi: Constify a variable. + riched20: Constify some variables. + msxml3: Constify some variables. + comctl32: Constify some variables. + wineps.drv: Use const-correct GetPrinterDataEx() instead of GetPrinterData(). + dbghelp: Use dbgstr_a() in case pointer is NULL. + mpr: Fix some memory leaks. + gdi32: Pass correct pointer value to HeapFree(). + +Colin Finck (2): + wininet: Always pass a variable as lpNumberOfBytesWritten on a WriteFile call if lpOverlapped is set to NULL. + comctl32: Use a clip region when collapsing the treeview. + +Dan Hipschman (7): + gdi32: Add tests for GetTextFace. + riched20/tests: Add tests for OLE interface. + riched20/tests: Add a test for creating ITextDocument. + kernel32/tests: Add tests for TLS functions. + gdi32: Return the correct value from GetTextFace. + riched20: Implement ITextDocument_fnGetSelection. + user32: Redefine internal pop-up tracking flags to avoid conflicts. + +Dan Kegel (8): + advpack: Don't close a handle if it wasn't opened. + dsound: Don't free buffer if it's owned by alsa. + winmm/tests: Initialize MIXERLINECONTROLSA before calling mixerGetLineControlsA. + gdi32: GdiConvertToDevmodeW should not refer to unintialized name bytes. + kernel32/tests: Initialize a few variables. + msxml3/tests: VT_EMPTY is not a string. + user32: Fix buffer length thinko in dde_client.c. + wininet: InternetCrackUrlW: For URLs that have no urlpath, native clears lpszUrlPath. + +Detlef Riekenberg (2): + avifil32: The array index is 0-based. + rpcrt4: Add a stub for I_RpcBindingInqTransportType. + +Dmitry Timoshkov (29): + gdi32: Print the assigned world transform. + gdi32: Use 0xffff as a default character as Vista does. + user32: Add a test for MNS_NOTIFYBYPOS, make it pass under Wine. + kernel32: Make GetModuleFileName set ERROR_INSUFFICIENT_BUFFER like win2k3 and vista do. + winmm: Add the tests for mmioOpen and mmioSetBuffer, make them pass under Wine. + winmm: Clear the fccType in mmioDescend for a not RIFF/LIST case. + gdi32: Add a test for combined mapping mode/world transform changes. + wine.inf: Add Baltic font substitutions. + gdi32: Extend the font substitution test, make it pass under Wine. + gdi32: Make GetOutlineTextMetrics set tmDigitizedAspectX/Y to real values as GetTextMetrics does. + gdi32: Perform font height scaling with higher precision. + gdi32: Initialize otmMacAscent, otmMacDescent, otmMacLineGap in outline text metrics. + gdi32: Don't forget to update the glyph advance in the case of a custom transformation. + gdi32: Font scaling transform is performed separately. + gdi32: Perform the world transform separately from font scaling. + gdi32: Apply the custom transform to a glyph only if it's not an identity one. + gdi32: Don't cache glyph metrics if they have a custom transformation. + gdi32: Don't return cached glyph metrics if a custom transformation was requested. + gdi32: Scale outline font metrics. + gdi32: Indent a block of code using 4 spaces instead of 5. + gdi32: Add a test for outline text metrics. + gdi32: Perform correct glyph scaling even if font metrics haven't been cached yet. + user32: Make test_SetForegroundWindow() the last message test. + include: Remove a semicolon from a DECL_WINELIB_TYPE_AW use. + include: Undefine a custom DECL_WINELIB_DBT_TYPE_AW macro at the end of the file. + winmm: Add another test confirming that mmioDescend does set fccType of non RIFF/LIST chunks to 0. + mciavi32: Read the stream header in order to determine its type. + user32: Add a test for focus behaviour on minimize/restore. + wordpad: Pass correct parameters to WM_SIZE message handler. + +Dylan Smith (35): + wordpad: Added style to the richedit control to not hide selection. + wordpad: Fixed the font size validation for the toolbar's combobox. + wordpad: Apply changes on dropdown selection for comboboxes on toolbar. + wordpad: Fixed calculations for the paragraph format dialog. + wordpad: Fixed bugs that prevented setting alignment through dialog. + wordpad: Fixed a bug in setting the recent file list in the registry. + winemine: Beginner mode should have one more row and column. + winemine: Adding flag before the game starts shouldn't start the timer. + winemine: Set mines after first choice. + winemine: Middle click drag should move the box highlighting. + winemine: The number of mines should be visible before first choice. + winemine: Increased buffer size for player names. + richedit: Allow cursor to move over trailing spaces in wrapped lines. + richedit: Trailing spaces should not affect alignment shift length. + richedit: bCaretAtEnd should not be reset from rewrapping text. + richedit: Tests for undo coalescing. + richedit: Added missing defines and structures to richedit.h. + richedit: Null pointer check missing on optional parameter. + richedit: Show caret after pasting or streaming in text. + richedit: Prevented NULL value from being used to avoid a page fault. + richedit: Prevented an assertion error on startup when run on Windows. + richedit: Fixed the forward word movement bug. + richedit: Fixed a bug preventing NULL pointers from being in text. + richedit: Added tests reveal a problem with EM_SETCHARFORMAT's affect on the undo stack. + richedit: Moved function declarations in header to reflect locations of definitions. + richedit: Corrected the conversion used for the initial font size. + richedit: Fixed bug preventing bold from being set with EM_SETCHARFORMAT. + richedit: Make cursor visible when selecting via mouse above/below editor. + richedit: Implemented undo coalescing to group typing events. + richedit: Removed redundant code for getting the insert style. + richedit: Set error codes and stop parsing for some rtf syntax errors. + richedit: Fixed mistake that didn't cause a bug. + richedit: Caret size must match font size characters to be inserted. + riched32: Added class style to process double click events. + richedit: Ensure caret is seen if moved past end of view over trailing spaces. + +Eric Durbin (10): + iphlpapi: Implement getInterfaceStatsByName on FreeBSD. + iphlpapi: Implement getNumUdpEntries on FreeBSD. + iphlpapi: Implement getUDPStats on FreeBSD. + iphlpapi: Implement getIPStats on FreeBSD. + iphlpapi: Downgrade some ERR messages to WARN. + iphlpapi: Implement getICMPStats on FreeBSD. + iphlpapi: Fix a typo resulting in wrong variable assignment. + iphlpapi: Implement getTCPStats on FreeBSD. + iphlpapi: Implement getNumArpEntries on FreeBSD. + iphlpapi: Implement getArpTable on FreeBSD. + +Eric Pouech (3): + winhelp: Properly quit winhelp when no file are given on command line. + winhelp: Added the options menu. + winhelp: Removed the main history button, and use the item in Options menu instead. + +Filipe Ferreira (1): + winecfg: Added Windows registration information setting. + +Francois Gouget (5): + A couple of spelling fixes. + configure: Detect and use gld/gnm/gar as alternatives to ld/nm/ar, especially for winegcc. + configure: Fix the isinf() detection. Fixes compilation on Solaris. + shlwapi: Don't use Unix functions for case sensitive string comparisons. + wined3d: Add a trailing '\n' to a couple of shader_addline() calls. + +Gerald Pfeifer (2): + comctl32: tooltips: Adjust the type of three loop variables from INT to UINT. + winex11: Remove two unused parameters from BITBLT_GetSrcArea(). + +Guy Albertelli (3): + comctl32: listview: Change header control create act like native for LVS_NOCOLUMNHEAD. + comctl32: listview: Show the header when updating header size if not LVS_NOCOLUMNHEADER. + comctl32: listview: Implement LVS_NOCOLUMNHEADER support for WM_STYLECHANGED message. + +H. Verbeet (14): + wined3d: Add support for ARB_color_buffer_float. + wined3d: Use gl_Color and gl_SecondaryColor to support more varyings in SM3.0 shaders. + wined3d: Handle depth formats like any other format in CheckDeviceFormat. + wined3d: Report WINED3DFMT_FLAG_FILTERING on WINED3DFMT_D24X8. + wined3d: Report post pixelshader blending on WINED3DFMT_A16B16G16R16F. + wined3d: Half float formats need ARB_TEXTURE_FLOAT as well. + d3d8: Use color_match() in alpha_test(). + d3d9: Use color_match() in alpha_test(). + wined3d: Explicitly enable depth buffer writing in depth_blt(). + d3d9: Use color_match() in fog_with_shader_test(). + d3d: Allow more imprecision in the texop test. + d3d9: Unset the pixel shader at the end of cnd_test(). + wined3d: Report WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING. + wined3d: Delete depth_blt_texture on IWineD3DDeviceImpl_Uninit3D(). + +Hans Leidekker (6): + wininet: Clear last error upon successful return from HttpSendRequest. + wininet: Improve some traces. + wininet: Send a 'Pragma: no-cache' header if asked for. + wininet: Resolve hostname once per connection. + wininet: Win64 compatibility fixes. + wininet: Make a test pass on IE6. + +Huw Davies (9): + gdi32: Initialize the handle table. + gdiplus: GdipCreatePen2 should make a copy of the brush. + ntdll: Free the correct buffer in the test. + netapi32: Free the correct pointers. + kernel32: Fix typo. + d3d8: Fix typo in test. + inetcomm: Fully initialize start and length. + winspool.drv: Make sure the printer driver registry entry exists. + localspl: Ensure that we load winspool before spoolss to work around a circular dependence. + +Hwang YunSong(황윤성) (2): + winhlp32: Updated Korean resource. + shell32: Updated Korean resource. + +Jacek Caban (60): + mshtml: Added IHTMLElement::get_id implementation. + mshtml: Added IHTMLElement::put_id implementation. + mshtml: Added IDispatchEx support to HTMLSelectElement. + mshtml: Added fdexNameEnsure support to IDidpatchEx implementation. + mshtml: Use heap_alloc_zero in HTMLElementCollection_Create. + mshtml: Added missing tids to HTMLCommentElement. + mshtml: Added more IDispatchEx tests. + mshtml: Change backslashes to shashes in URLs passed to IHTMLStyle::put_backgroundImage. + mshtml: Added IHTMLStyle::put_background implementation. + mshtml: Added IHTMLStyle::put_color implementation. + mshtml: Added IHTMLElement2::focus implementation. + mshtml: Use heap_alloc_zero to allocate OmNavigator. + mshtml: Added IHTMLDOMNode::get_nodeValue implementation. + mshtml: Added IHTMLDOMNode::put_nodeValue implementation. + mshtml: Added IHTMLElement2::put_accessKey implementation. + mshtml: Better stub for IHTMLElement::setAttribute with NULL nselem. + mshtml: Added IHTMLElement2::get_clientWidth implementation. + mshtml: Added IHTMLElement::get_clientHeight implementation. + mshtml: Added IHTMLInputElement::put_value implementation. + mshtml: Forward HTMLInputElement IDispatch calls to IDispatchEx implementation. + urlmon: Make mk protocol behave like IE7. + mshtml: Better timer handling. + mshtml.idl: Added DispHTMLGenericElement declaration. + mshtml.idl: Added IHTMLGenericElement declaration. + mshtml: Initialize node object from child node's constructors. + mshtml: Added IHTMLDocument2::createElement implementation. + mshtml: Added IHTMLGenericElement implementation. + mshtml: Added IDispatchEx support to HTMLGenericElement. + mshtml: Added createElement test. + shdocvw: Added WebBrowser's IDispatch methods implementation. + mshtml: Added IHTMLDOMNode::appendChild implementation. + mshtml: Added IHTMLDocument3::createTextNode implementation. + mshtml: Return NULL instead of empty string in IHTMLElement::get_className. + mshtml: Added IHTMLElement::put_className implementation. + mshtml: Added IHTMLImgElement::put_src implementation. + mshtml: Added onclick attribute support. + mshtml: Use heap_alloc_zero in NSContainer_Create. + mshtml: Added generic HTML event listener and use it for click event. + mshtml: Added IHTMLElement::put_onclick implementation. + mshtml: Added keyup event support. + mshtml: Added IHTMLElement::put_onkeyup implementation. + mshtml: Added IHTMLElement2::get_tabIndex implementation. + mshtml: Added IHTMLElement2::put_tabIndex implementation. + mshtml: Added support to accessing child nodes by index in IHTMLDOMChildrenCollection. + mshtml: Fixed argument checking in IHTMLDOMChildrenCollection::item. + mshtml: Added IHTMLDOMNode::removeChild implementation. + mshtml: Added IHTMLDOMNode::hasChildNodes implementation. + mshtml: Added IHTMLSelectElement::put_value implementation. + mshtml: Return NULL instead of empty string in IHTMLSelectElement::get_value. + mshtml: Added IHTMLSelectElement::put_onchange implementation. + mshtml: Added IHTMLElement::get_title implementation. + mshtml: Added IHTMLElement::put_title implementation. + mshtml: Added IHTMLInputElement::put_disabled implementation. + mshtml: Added IHTMLSelectElement::get_type implementation. + mshtml: Forward HTMLSelectElement's IDispatch functions to IDispatchEx implementation. + mshtml: Added IHTMLElement::get_offsetTop implementation. + mshtml: Added useful TRACEs. + mshtml: Added IHTMLDOMNode::get_parentNode implementation. + mshtml: Added DOCUMENT_NODE type support. + urlmon: Make file protocol invalid URL handling behave like IE7. + +James Hawkins (38): + ddraw: Reset the viewport data before each test. + msi: Rewrite the ProcessComponents test to only check the registry changes. + msi: Don't publish components to the Installer key. + msi: Determine the installation context after reading properties from the command line. + msi: Fix the ProcessComponents action to handle the package context. + msi: Rewrite the RegisterUser test to only check the registry changes. + msi: Fix the RegisterUser action to handle the package context. + msi: Rewrite the PublishFeatures test to only check the registry changes. + msi: Don't publish features to an invalid location. + msi: Fix the PublishFeatures action to handle the package context. + msi: Rewrite the RegisterProduct test to only check the registry changes. + msi: Don't publish the upgrade key to an invalid location. + msi: Factor out the publishing of installation properties. + msi: Test the RegisterProduct action with the machine context. + msi: Rewrite the PublishProduct test to only check the registry changes. + msi: Factor out publishing icon files. + msi: Factor out publishing the product source list. + msi: Don't set an invalid install property in PublishProduct. + msi: Don't publish the product to an invalid location. + msi: Factor out publishing the product properties. + msi: Squash the package code property. + msi: Allow checking a REG_MULTI_SZ string. + msi: Publish a few more product properties. + msi: Publish media disks whether the drive type is removable or not. + msi: Publish the UpgradeCode in PublishProduct. + msi: Test the PublishProduct action with the machine context. + msi: Open the local user data product key for the machine context. + msi: Fix the published location of the upgrade code for the machine context. + msi: Create the SourceList key in msi_publish_sourcelist. + msi: Add more tests for MsiQueryFeatureState. + msi: Handle the user managed context in MsiQueryFeatureState. + msi: Handle the machine context in MsiQueryFeatureState. + msi: Reimplement MsiGetUserInfo. + msi: Add tests for MsiGetUserInfo. + mscms: Only check the first three characters of the color space name. + urlmon: Fix a few test failures in IE7. + msi: Add another MsiGetFileVersionTest. + msi: Don't overwrite a file that has a greater or equal version to the source file. + +Jeff Zaroyko (1): + ws2_32: Ignore lpFrom for connected sockets. + +John Klehm (4): + winex11: Add comments explaining wintab cursor slotting, type, and clarify x11 config. + winex11: Always assign a tablet cursor type. + winex11: Cursor iteration is now done by checking ACTIVE cursors. + winex11: Place tablet cursors in slots based on type. + +Jon Griffiths (10): + tapi.h: Fix struct member names. + include/msvcrt: Wrap remaining msvcrt headers for C++ compilation. + include/rpcproxy.h: Fix incorrect include guard comment. + winedbg: Add support for printing c++ bool values. + include: Provide wide char definitions for CFSTR_*. + oleaut32/tests: Fix invalid free (found by valgrind). + oleidl.h: Fix spelling of OLECONTF_ONLYUSER (reported by Marcos Gutiérrez Batz). + dbghelp: Implement SymEnumerateSymbols64. + ntdll: Implement [Rtl]InitializeCriticalSectionEx. + c2man: Correct extension for non-dlls (based on a patch by Vijay Kamuju). + +Joris Huizer (3): + user32/tests: Copy/paste fix. + gdiplus: font: Ensure to release resources. + gdiplus: Change tmw field of GpFontFamily into an embedded structure. + +Juan Lang (26): + inetmib1: Add stub dll. + inetmib1: Add stub for SnmpExtensionInit. + inetmib1: Add tests for SnmpExtensionInit. + inetmib1: Add stub for SnmpExtensionQuery. + inetmib1: Add tests for SnmpExtensionQuery. + inetmib1: Improve SnmpExtensionInit stub. + inetmib1: Improve SnmpExtensionQuery stub. + inetmib1: Add a mechanism for initializing supported OIDs, and use it in SnmpExtensionInit. + inetmib1: Add initialization function for getting the MIB2 number of interfaces. + inetmib1: Implement SnmpExtensionQuery. + inetmib1: Support querying the MIB2 number of interfaces. + inetmib1: Support the MIB2 interface table. + inetmib1: Support the MIB2 IP statistics. + inetmib1: Support the MIB2 ICMP statistics. + inetmib1: Support the MIB2 IP address table. + inetmib1: Use a helper function to get the item and instance of the MIB2 interface table. + inetmib1: Use a helper function to get the item from the Oid. + inetmib1: Use a helper function to get the item and instance of the MIB2 IP address table. + inetmib1: Support the MIB2 TCP statistics. + inetmib1: Support the MIB2 IP route table. + inetmib1: Support the MIB2 IP net (ARP) table. + inetmib1: Use a helper function to set the Oid with an IP address-based instance. + inetmib1: Use a helper function to set the Oid with an integer instance. + inetmib1: Use a helper function to set the Oid with an item. + inetmib1: Support the MIB2 UDP statistics. + inetmib1: Sort the tables keyed by IP address, and use bsearch to find entries in them. + +Kai Blin (6): + rpcrt4: Fix some A/W use in error messages. + rpcrt4: Ignore the AuthzSvr parameter for RPC_C_AUTHN_WINNT. + advapi32: Fix lsa tests for domain members. + netapi32: tests/access: Don't clutter up standalone Windows boxes. + netapi32: Remove double free test from apibuf tests. + netapi32: Don't test NetUserChangePassword for now. + +Kirill K. Smirnov (1): + kernel32: Add stubs for [G|S]etConsoleDisplayMode. + +Lei Zhang (5): + comctl32: Don't rearrange icons / update scroll bar when destroying a listview. + comctl32: Support LVCF_SUBITEM in LVM_GETCOLUMN. + gdi32: Check for regular fonts by style instead of style name. + comctl32: Use the system variable pitch font for ip address controls. + mshtml: Remove unneeded variable. + +Louis Lenders (3): + kernel32: Fix typo in SetProcessAffinityMask. + advapi32: Add stub for GetAuditedPermissionsFromAcl{A/W}. + d3dx9_*: Add version resources. + +Maarten Lankhorst (30): + quartz: Improve the directsound renderer a bit. + quartz: Set data length in avi decompressor. + include: Add definitions for IBasicVideo2 interface. + include: Add definitions for IAMFilterMiscFlags interface. + winemp3: Try to find a valid header instead of failing immediately. + qcap: Capture pin should have an IAMStreamConfig. + quartz: Forward some messages from IMediaSeekingPassThru. + quartz: Add the ability to force a pin to use a certain renderer. + quartz: Only query for event interface when there is a filtergraph. + quartz: Expose some methods so that a custom allocator can be created. + quartz: Try to render any existing renderers before creating a new one. + quartz: Implement MediaControl_GetState. + quartz: Implement IMediaSeeking in the video renderer. + quartz: Implement IBasicVideo2 for the filtergraph. + include: Add definitions for VMR-9 interface. + quartz: Implement GraphConfig_Reconfigure. + quartz: Implement VideoRenderer_GetCurrentImage. + quartz: Have thread safety in memallocator. + quartz: DSoundRender shouldn't delete buffer when already connected. + quartz: Only enumerate renderers if bRender is set in filtermapper. + quartz: Add support for VideoInfoHeader2 to AVI Decompressor. + quartz: Clear pin value if not connected. + quartz: Handle case where ReceiveConnection is called on an already connected pin. + quartz: Remove dead code from DSoundRender. + quartz: Create thread after connection is made. + quartz: Make the memory allocator emit more warnings and fix race condition. + quartz: Downgrade a fixme to a warn in dsoundrender. + quartz: Make removing filters work slightly better. + quartz: Make FilterGraph_Connect and ConnectDirect behave better. + quartz: Fix Render and RenderFile. + +Marcus Meissner (2): + ws2_32/tests: Initialize memory to send. + ws2_32/tests: Initialize buffer to avoid valgrind warning. + +Michael Karcher (1): + ddraw: Ensure to load wined3d before attempting to create a clipper. + +Michael Stefaniuc (2): + riched20: Remove redundant NULL check before heap_free (Smatch). + winedbg: Fix "floating pointer" typo. + +Mikołaj Zalewski (4): + winhlp32: Update Polish translation. + comdlg32: Implement CDM_GETFOLDERIDLIST. + comdlg32/tests: Make sure no ANSI strings are passed to Unicode functions. + kernel32: Improve Esperanto locale definition. + +Nikolay Sivov (16): + gdiplus: Check pointer in GdipGetLineRectI. + gdiplus: Implemented GdipAddPathRectangles with tests. + gdiplus: Stub for GdipFlush. + gdiplus: Implemented GdipGetPathData with test. + gdiplus: Fix GdipGetPathData implementation and test. + gdiplus: GdipPathIterGetCount implementation. + gdiplus: GdipSetPathMarker implementation. + gdiplus: GdipClearPathMarkers implementation. + gdiplus: Implementation of GdipAddPathPolygon with tests. + gdiplus: Implemented GdipCloneImageAttributes. + gdiplus: Implemented GdipGetPenEndCap. + gdiplus: Implemented GdipGetPenLineJoin, GdipGetPenMiterLimit. + gdiplus: Added GdipGetPenStartCap. + gdiplus: Implemetned GdipGetPenUnit. + gdiplus: Implemented GdipGetPenWidth. + gdiplus: Implemented GdipGetPenDashCap197819. + +Owen Rudge (7): + shell32: Add support for WantsForDISPLAY and HideAsDeletePerUser to the register_coclasses routine. + wine.inf: Add cplfile (control panel applet) association. + shell32: Register Control Panel namespace folder. + shell32: Ensure the correct applet is loaded in multi-applet control panels. + shell32: Populate comment column in Control Panel. + shell32/tests: Rename shfldr_netplaces test to shfldr_special, for all special folders. + shell32/tests: Add basic ParseDisplayName test for control panel. + +Paul Vriens (22): + tools/winapi: Fix typo in the generated header. + advapi32/tests: Fix a test on NT4. + msi/tests: Fix some test failures. + setupapi/tests: Fix some typos. + oleaut32/tests: Remove some stray spaces from the ok message. + user32/tests: Skip tests if functions are not implemented. + setupapi/tests: Skip all tests on Win9x and WinMe. + setupapi/tests: Remove win9x specifics from testDeviceRegistryPropertyW. + setupapi/tests: Remove win9x specifics from testDevRegKey. + setupapi/tests: Remove some function pointer checks from testRegisterDeviceInfo. + setupapi/tests: Remove win9x specifics from testCreateDeviceInfo. + setupapi/tests: Remove win9x specifics from testInstallClass. + setupapi/tests: Remove last win9x references. + setupapi/tests: Prevent crash on NT4. + setupapi/tests: Remove a registry key on failure for NT4. + setupapi/tests: Fix a test on NT4. + setupapi/tests: Add a simple test for the DelReg directive. + shell32/tests: Skip some tests if functions are not available. + kernel32/tests: Add some tests for GetConsoleCursorInfo. + kernel32: Fix return values of GetConsoleCursorInfo. + shlwapi/tests: Fix a test on Vista. + shlwapi/tests: Fix another test on Vista. + +Petr Dlouhý (2): + gdiplus: Stub implementation of GdipImageGetFrameDimensionsCount + test. + shlwapi: UrlCanonicalize will canonize address in format "file://localhost/c:/" correctly. + +Philip Nilsson (1): + msvcrt: Make EXCEPTION_PRIV_INSTRUCTION generate SIGILL. + +Przemysław Białek (1): + gdiplus: Implementation of function GdipDrawEllipse. + +Rob Shearman (40): + rpcrt4: Fix ndr_marshall tests to cope with using pointer ids instead of using pointer values. + rpcrt4: Save the previous BufferLength in test_ndr_buffer and use it when testing the expected buffer length after the NdrFreeBuffer call. + rpcrt4: Reduce the timeout of waiting on the stop event in the server test to one second. + rpcrt4: Zero the memory of the s1 structure in test_simple_struct to avoid a Valgrind warning. + Update generated packing tests using current headers. + rpcrt4: Rename RPCRT4_SendAuth to RPCRT4_SendWithAuth. + rpcrt4: Add new function RPCRT4_ReceiveWithAuth to receive a fragment and return the authentication data received, if any. + rpcrt4: Make RpcAssoc_BindConnection use RPCRT4_ReceiveWithAuth instead of RPCRT4_Receive. + include: Update the MIDL_STUB_MESSAGE structure. + shell32: Free the correct pointer in XDG_UserDirLookup. + wininet: Fix memory leak in HTTP_DeleteCustomHeader. + rpcrt4: Initialise UniquePtrCount in NdrClientInitializeNew. + rpcrt4: Use abrtitrary pointer identifiers when marshalling pointers instead of using pointer values. + widl: Fix generation of the type format string for conformant-varying structures. + ole32: Include enumx.h in enumx.c to get the declarations of the functions. + ole32: Include ole2.h in ole32_main.c to type-check the function signature of OleMetafilePictFromIconAndLabel. + ole32: Remove unused BIGBLOCKFILE_GetSize. + ole32: Include compobj_private.h in oleobj.c to type-check the function signatures of DataAdviseHolder_OnConnect and DataAdviseHolder_OnDisconnect. + include: Add declarations for OleNoteObjectVisible, GetConvertStg and OleDoAutoConvert to ole2.h. + include: Add new bitfields to MIDL_STUB_MESSAGE added in Vista SDKs. + rpcrt4: Initialise UniquePtrCount in NdrServerInitializeNew. + rpcrt4: Add test for using a conformant varying structure with pointers. + widl: Replace code to round up values and calculate padding with macros to improve readability. + widl: Fix the embedded pointer offsets in generated code when the containing structure has padding. + rpcrt4: Factor out string validation from NDR unmarshalling functions into a separate function, validate_string_data. + rpcrt4: Fix NdrConformantVaryingStructUnmarshall to use buffer memory if applicable and to reuse memory for embedded pointers. + widl: Factor out the finding of a registered type to reduce code duplication. + widl: Set the type of the type_t node constructured for dispinterfaces to RPC_FC_IP, like we do for interfaces. + widl: Fix crash in find_array_or_string_in_struct if the structure or union has no fields or cases. + widl: Fix the types of enums with the v1_enum attribute applied. + widl: Fix type_memsize to follow aliases so that the correct size is calculated. + widl: Fix check_remoting_fields to enumerate the correct list of fields. + include: Add the local attribute to IShellExecuteHookA/W since they use an undefined structure. + include: Add more IXMLDOMNotation, IXMLDOMEntity, IXMLDOMEntityReference and IXMLDOMImplementation interfaces to xmldom.idl. + include: Don't import files in control.idl that aren't imported on Windows. + include: Add more interfaces and types to msinkaut.idl. + rpcss: Implement endpoint-mapper server using DCE/RPC. + rpcrt4: Use DCE/RPC to contact the endpoint-mapper server. + rpcrt4/rpcss: Remove old named pipe code for communicating with RPCSS process. + rpcrt4: Add tests for endpoint mapper functions. + +Roderick Colenbrander (4): + wined3d: Add a Geforce9 driver version (right now garbage is returned). + wined3d: Update the Nvidia driver version to 173.41 and also put it in the right format e.g. 7.15.11.7341 instead of 7.15.10.17341. + wined3d: Update the d3dusage query mask with 0x100000 (vertextexture). + wined3d: Fix a usage flags conflict. + +Roy Shea (3): + user32: Initialize hdd HDDEDATA to NULL (valgrind). + dsound/tests: Removed test depending on value of undefined variable. + dsound/tests: Added additional tests of IDirectSound_CreateSoundBuffer. + +Scott Ritchie (1): + wine.desktop: Add application/x-msi and change "emulator" to "program loader". + +Simon Richter (1): + widl: Write string lengths in host endianness. + +Ted Percival (1): + regedit: Interpret REG_DWORD as unsigned in editor. + +Vitaliy Margolen (2): + dxdiagn: PhysicalMemory parameter is a string not long long. + dxdiagn: Use helper functions for adding properties to container. + +Vitaly Lipatov (3): + user32: Implemented processing SPI_{GET/SET}SNAPTODEFBUTTON for SystemParametersInfo. + user32: Implemented processing SPI_{GET/SET}WHEELSCROLLCHARS for SystemParametersInfo. + user32: Add test for SPI_{GET/SET}WHEELSCROLLCHARS for SystemParametersInfo. + +Vladimir Pankratov (6): + shell32: Update Russian translation. + mshtml: Update Russian translation. + regedit: Update Russian translation. + oleview: Add Russian translation. + taskmgr: Add Russian translation. + hhctrl.ocx: Update Russian translation. + +Zac Brown (4): + mshtml: Initialize variables in a couple structs. + ntdll/tests: Add tests for (Rtl)IsTextUnicode to verify that IS_TEXT_UNICODE_CONTROLS and IS_TEXT_UNICODE_REVERSE_CONTROLS are not mutually exclusive. + winealsa.drv: Initialize a variable in MIX_close. + shell32: Add stub implementation for SHGetIconOverlayIndex[AW]. + +Zhangrong Huang (1): + kernel32: Add locale script tag resources. + +-- +Alexandre Julliard +julliard@winehq.org diff --git a/Make.rules.in b/Make.rules.in index 1d038416b40..b46a573e69d 100644 --- a/Make.rules.in +++ b/Make.rules.in @@ -46,6 +46,7 @@ LN_S = @LN_S@ TOOLSDIR = @TOOLSDIR@ AS = @AS@ LD = @LD@ +NM = @NM@ LDFLAGS = @LDFLAGS@ PRELINK = @PRELINK@ RM = rm -f diff --git a/Makefile.in b/Makefile.in index de131bda0a5..f2dbcfc3789 100644 --- a/Makefile.in +++ b/Makefile.in @@ -291,6 +291,8 @@ ALL_MAKEFILES = \ dlls/imm32/tests/Makefile \ dlls/inetcomm/Makefile \ dlls/inetcomm/tests/Makefile \ + dlls/inetmib1/Makefile \ + dlls/inetmib1/tests/Makefile \ dlls/infosoft/Makefile \ dlls/infosoft/tests/Makefile \ dlls/initpki/Makefile \ @@ -717,6 +719,8 @@ dlls/imm32/Makefile: dlls/imm32/Makefile.in dlls/Makedll.rules dlls/imm32/tests/Makefile: dlls/imm32/tests/Makefile.in dlls/Maketest.rules dlls/inetcomm/Makefile: dlls/inetcomm/Makefile.in dlls/Makedll.rules dlls/inetcomm/tests/Makefile: dlls/inetcomm/tests/Makefile.in dlls/Maketest.rules +dlls/inetmib1/Makefile: dlls/inetmib1/Makefile.in dlls/Makedll.rules +dlls/inetmib1/tests/Makefile: dlls/inetmib1/tests/Makefile.in dlls/Maketest.rules dlls/infosoft/Makefile: dlls/infosoft/Makefile.in dlls/Makedll.rules dlls/infosoft/tests/Makefile: dlls/infosoft/tests/Makefile.in dlls/Maketest.rules dlls/initpki/Makefile: dlls/initpki/Makefile.in dlls/Makedll.rules diff --git a/VERSION b/VERSION index 1142d748f3d..85bcbfdecff 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Wine version 1.0 +Wine version 1.1.0 diff --git a/configure b/configure index cbbc708a44a..37814cb03fe 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for Wine 1.0. +# Generated by GNU Autoconf 2.61 for Wine 1.1.0. # # Report bugs to . # @@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='Wine' PACKAGE_TARNAME='wine' -PACKAGE_VERSION='1.0' -PACKAGE_STRING='Wine 1.0' +PACKAGE_VERSION='1.1.0' +PACKAGE_STRING='Wine 1.1.0' PACKAGE_BUGREPORT='wine-devel@winehq.org' ac_unique_file="server/atom.c" @@ -689,7 +689,11 @@ BISON AS ac_ct_AS LD +ac_ct_LD +NM +ac_ct_NM AR +ac_ct_AR ARFLAGS RANLIB STRIP @@ -1295,7 +1299,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Wine 1.0 to adapt to many kinds of systems. +\`configure' configures Wine 1.1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1364,7 +1368,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Wine 1.0:";; + short | recursive ) echo "Configuration of Wine 1.1.0:";; esac cat <<\_ACEOF @@ -1494,7 +1498,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Wine configure 1.0 +Wine configure 1.1.0 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1508,7 +1512,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Wine $as_me 1.0, which was +It was created by Wine $as_me 1.1.0, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -5458,8 +5462,10 @@ esac fi if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args. -set dummy ${ac_tool_prefix}ld; ac_word=$2 + for ac_prog in ld gld + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_LD+set}" = set; then @@ -5475,7 +5481,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_LD="${ac_tool_prefix}ld" + ac_cv_prog_LD="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -5495,11 +5501,15 @@ echo "${ECHO_T}no" >&6; } fi + test -n "$LD" && break + done fi -if test -z "$ac_cv_prog_LD"; then +if test -z "$LD"; then ac_ct_LD=$LD - # Extract the first word of "ld", so it can be a program name with args. -set dummy ld; ac_word=$2 + for ac_prog in ld gld +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_LD+set}" = set; then @@ -5515,7 +5525,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_LD="ld" + ac_cv_prog_ac_ct_LD="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -5534,6 +5544,10 @@ else echo "${ECHO_T}no" >&6; } fi + + test -n "$ac_ct_LD" && break +done + if test "x$ac_ct_LD" = x; then LD="ld" else @@ -5549,13 +5563,117 @@ ac_tool_warned=yes ;; esac LD=$ac_ct_LD fi +fi + +if test -n "$ac_tool_prefix"; then + for ac_prog in nm gnm + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NM"; then + ac_cv_prog_NM="$NM" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NM="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +NM=$ac_cv_prog_NM +if test -n "$NM"; then + { echo "$as_me:$LINENO: result: $NM" >&5 +echo "${ECHO_T}$NM" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$NM" && break + done +fi +if test -z "$NM"; then + ac_ct_NM=$NM + for ac_prog in nm gnm +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_NM"; then + ac_cv_prog_ac_ct_NM="$ac_ct_NM" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NM="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_NM=$ac_cv_prog_ac_ct_NM +if test -n "$ac_ct_NM"; then + { echo "$as_me:$LINENO: result: $ac_ct_NM" >&5 +echo "${ECHO_T}$ac_ct_NM" >&6; } else - LD="$ac_cv_prog_LD" + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_NM" && break +done + + if test "x$ac_ct_NM" = x; then + NM="nm" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + NM=$ac_ct_NM + fi fi if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. -set dummy ${ac_tool_prefix}ar; ac_word=$2 + for ac_prog in ar gar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_AR+set}" = set; then @@ -5571,7 +5689,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_AR="${ac_tool_prefix}ar" + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -5591,11 +5709,15 @@ echo "${ECHO_T}no" >&6; } fi + test -n "$AR" && break + done fi -if test -z "$ac_cv_prog_AR"; then +if test -z "$AR"; then ac_ct_AR=$AR - # Extract the first word of "ar", so it can be a program name with args. -set dummy ar; ac_word=$2 + for ac_prog in ar gar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_AR+set}" = set; then @@ -5611,7 +5733,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_AR="ar" + ac_cv_prog_ac_ct_AR="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -5630,6 +5752,10 @@ else echo "${ECHO_T}no" >&6; } fi + + test -n "$ac_ct_AR" && break +done + if test "x$ac_ct_AR" = x; then AR="ar" else @@ -5645,8 +5771,6 @@ ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi -else - AR="$ac_cv_prog_AR" fi ARFLAGS=rc @@ -7106,12 +7230,14 @@ done + for ac_header in \ AudioUnit/AudioUnit.h \ Carbon/Carbon.h \ CoreAudio/CoreAudio.h \ DiskArbitration/DiskArbitration.h \ IOKit/IOKitLib.h \ + alias.h \ alsa/asoundlib.h \ arpa/inet.h \ arpa/nameser.h \ @@ -7504,7 +7630,24 @@ done -for ac_header in netinet/in_pcb.h netinet/ip_var.h net/if.h net/if_arp.h net/if_dl.h net/if_types.h net/route.h netipx/ipx.h + + + + +for ac_header in \ + netinet/ip.h \ + net/if.h \ + net/if_arp.h \ + net/if_dl.h \ + net/if_types.h \ + net/route.h \ + netinet/if_ether.h \ + netinet/in_pcb.h \ + netinet/ip_icmp.h \ + netinet/ip_var.h \ + netinet/udp.h \ + netipx/ipx.h \ + do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -7528,6 +7671,9 @@ cat >>conftest.$ac_ext <<_ACEOF #ifdef HAVE_NETINET_IN_H # include #endif + #ifdef HAVE_NETINET_IP_H + # include + #endif #include <$ac_header> _ACEOF @@ -7572,7 +7718,10 @@ done -for ac_header in netinet/tcp_var.h + + + +for ac_header in netinet/tcp_var.h netinet/udp_var.h netinet/icmp_var.h netinet/tcp_timer.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -7587,6 +7736,9 @@ cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include + #ifdef HAVE_ALIAS_H + # include + #endif #ifdef HAVE_SYS_SOCKET_H # include #endif @@ -7596,6 +7748,18 @@ cat >>conftest.$ac_ext <<_ACEOF #ifdef HAVE_NETINET_IN_H # include #endif + #ifdef HAVE_NETINET_IP_H + # include + #endif + #ifdef HAVE_NETINET_IP_VAR_H + # include + #endif + #ifdef HAVE_NETINET_IP_ICMP_H + # include + #endif + #ifdef HAVE_NETINET_UDP_H + # include + #endif #ifdef HAVE_NETINET_TCP_H # include #endif @@ -21248,7 +21412,7 @@ cat >>conftest.$ac_ext <<_ACEOF int main () { -float f = 0.0; isinf(f) +float f = 0.0; int i=isinf(f) ; return 0; } @@ -21801,6 +21965,10 @@ ac_config_files="$ac_config_files dlls/inetcomm/Makefile" ac_config_files="$ac_config_files dlls/inetcomm/tests/Makefile" +ac_config_files="$ac_config_files dlls/inetmib1/Makefile" + +ac_config_files="$ac_config_files dlls/inetmib1/tests/Makefile" + ac_config_files="$ac_config_files dlls/infosoft/Makefile" ac_config_files="$ac_config_files dlls/infosoft/tests/Makefile" @@ -22762,7 +22930,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Wine $as_me 1.0, which was +This file was extended by Wine $as_me 1.1.0, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -22815,7 +22983,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -Wine config.status 1.0 +Wine config.status 1.1.0 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" @@ -23064,6 +23232,8 @@ do "dlls/imm32/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/imm32/tests/Makefile" ;; "dlls/inetcomm/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/inetcomm/Makefile" ;; "dlls/inetcomm/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/inetcomm/tests/Makefile" ;; + "dlls/inetmib1/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/inetmib1/Makefile" ;; + "dlls/inetmib1/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/inetmib1/tests/Makefile" ;; "dlls/infosoft/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/infosoft/Makefile" ;; "dlls/infosoft/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/infosoft/tests/Makefile" ;; "dlls/initpki/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/initpki/Makefile" ;; @@ -23487,14 +23657,14 @@ BISON!$BISON$ac_delim AS!$AS$ac_delim ac_ct_AS!$ac_ct_AS$ac_delim LD!$LD$ac_delim +ac_ct_LD!$ac_ct_LD$ac_delim +NM!$NM$ac_delim +ac_ct_NM!$ac_ct_NM$ac_delim AR!$AR$ac_delim +ac_ct_AR!$ac_ct_AR$ac_delim ARFLAGS!$ARFLAGS$ac_delim RANLIB!$RANLIB$ac_delim STRIP!$STRIP$ac_delim -WINDRES!$WINDRES$ac_delim -LN_S!$LN_S$ac_delim -LN!$LN$ac_delim -GREP!$GREP$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 82; then @@ -23556,6 +23726,10 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +WINDRES!$WINDRES$ac_delim +LN_S!$LN_S$ac_delim +LN!$LN$ac_delim +GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim LDCONFIG!$LDCONFIG$ac_delim INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim @@ -23636,7 +23810,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 78; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 82; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/configure.ac b/configure.ac index a21fccb25b7..e5e8d111f45 100644 --- a/configure.ac +++ b/configure.ac @@ -172,8 +172,9 @@ then fi AC_CHECK_TOOLS(AS,[gas as],as) -AC_CHECK_TOOL(LD,ld,ld) -AC_CHECK_TOOL(AR,ar,ar) +AC_CHECK_TOOLS(LD,[ld gld],ld) +AC_CHECK_TOOLS(NM,[nm gnm],nm) +AC_CHECK_TOOLS(AR,[ar gar],ar) AC_SUBST(ARFLAGS,rc) AC_PROG_RANLIB AC_CHECK_TOOL(STRIP,strip,strip) @@ -242,6 +243,7 @@ AC_CHECK_HEADERS(\ CoreAudio/CoreAudio.h \ DiskArbitration/DiskArbitration.h \ IOKit/IOKitLib.h \ + alias.h \ alsa/asoundlib.h \ arpa/inet.h \ arpa/nameser.h \ @@ -358,8 +360,20 @@ AC_CHECK_HEADERS([sys/mount.h sys/statfs.h sys/user.h sys/vfs.h],,, # include #endif]) -AC_CHECK_HEADERS([netinet/in_pcb.h netinet/ip_var.h net/if.h net/if_arp.h net/if_dl.h net/if_types.h net/route.h netipx/ipx.h],,, - [#include +AC_CHECK_HEADERS(\ + netinet/ip.h \ + net/if.h \ + net/if_arp.h \ + net/if_dl.h \ + net/if_types.h \ + net/route.h \ + netinet/if_ether.h \ + netinet/in_pcb.h \ + netinet/ip_icmp.h \ + netinet/ip_var.h \ + netinet/udp.h \ + netipx/ipx.h \ +,,,[#include #ifdef HAVE_SYS_SOCKET_H # include #endif @@ -368,10 +382,16 @@ AC_CHECK_HEADERS([netinet/in_pcb.h netinet/ip_var.h net/if.h net/if_arp.h net/if #endif #ifdef HAVE_NETINET_IN_H # include + #endif + #ifdef HAVE_NETINET_IP_H + # include #endif]) -AC_CHECK_HEADERS([netinet/tcp_var.h],,, +AC_CHECK_HEADERS([netinet/tcp_var.h netinet/udp_var.h netinet/icmp_var.h netinet/tcp_timer.h ],,, [#include + #ifdef HAVE_ALIAS_H + # include + #endif #ifdef HAVE_SYS_SOCKET_H # include #endif @@ -381,6 +401,18 @@ AC_CHECK_HEADERS([netinet/tcp_var.h],,, #ifdef HAVE_NETINET_IN_H # include #endif + #ifdef HAVE_NETINET_IP_H + # include + #endif + #ifdef HAVE_NETINET_IP_VAR_H + # include + #endif + #ifdef HAVE_NETINET_IP_ICMP_H + # include + #endif + #ifdef HAVE_NETINET_UDP_H + # include + #endif #ifdef HAVE_NETINET_TCP_H # include #endif]) @@ -1606,7 +1638,7 @@ fi dnl Check for isinf AC_CACHE_CHECK([for isinf], ac_cv_have_isinf, - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[float f = 0.0; isinf(f)]])],[ac_cv_have_isinf="yes"],[ac_cv_have_isinf="no"])) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[float f = 0.0; int i=isinf(f)]])],[ac_cv_have_isinf="yes"],[ac_cv_have_isinf="no"])) if test "$ac_cv_have_isinf" = "yes" then AC_DEFINE(HAVE_ISINF, 1, [Define to 1 if you have the `isinf' function.]) @@ -1814,6 +1846,8 @@ AC_CONFIG_FILES([dlls/imm32/Makefile]) AC_CONFIG_FILES([dlls/imm32/tests/Makefile]) AC_CONFIG_FILES([dlls/inetcomm/Makefile]) AC_CONFIG_FILES([dlls/inetcomm/tests/Makefile]) +AC_CONFIG_FILES([dlls/inetmib1/Makefile]) +AC_CONFIG_FILES([dlls/inetmib1/tests/Makefile]) AC_CONFIG_FILES([dlls/infosoft/Makefile]) AC_CONFIG_FILES([dlls/infosoft/tests/Makefile]) AC_CONFIG_FILES([dlls/initpki/Makefile]) diff --git a/dlls/Makefile.in b/dlls/Makefile.in index 0ff48129645..e2c2f52ab10 100644 --- a/dlls/Makefile.in +++ b/dlls/Makefile.in @@ -113,6 +113,7 @@ BASEDIRS = \ imagehlp \ imm32 \ inetcomm \ + inetmib1 \ infosoft \ initpki \ inkobj \ @@ -310,6 +311,7 @@ TESTSUBDIRS = \ hlink/tests \ imm32/tests \ inetcomm/tests \ + inetmib1/tests \ infosoft/tests \ iphlpapi/tests \ itss/tests \ diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index e9a3ccc5516..4189458a7eb 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -230,8 +230,8 @@ # @ stub GetAccessPermissionsForObjectW @ stdcall GetAce(ptr long ptr) @ stdcall GetAclInformation(ptr ptr long long) -# @ stub GetAuditedPermissionsFromAclA -# @ stub GetAuditedPermissionsFromAclW +@ stdcall GetAuditedPermissionsFromAclA(ptr ptr ptr ptr) +@ stdcall GetAuditedPermissionsFromAclW(ptr ptr ptr ptr) @ stdcall GetCurrentHwProfileA(ptr) @ stdcall GetCurrentHwProfileW(ptr) @ stdcall GetEffectiveRightsFromAclA(ptr ptr ptr) diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index 333ad86bacf..2f9132968b7 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -3442,6 +3442,27 @@ DWORD WINAPI GetExplicitEntriesFromAclW( PACL pacl, PULONG pcCountOfExplicitEntr return ERROR_CALL_NOT_IMPLEMENTED; } +/****************************************************************************** + * GetAuditedPermissionsFromAclA [ADVAPI32.@] + */ +DWORD WINAPI GetAuditedPermissionsFromAclA( PACL pacl, PTRUSTEEA pTrustee, PACCESS_MASK pSuccessfulAuditedRights, + PACCESS_MASK pFailedAuditRights) +{ + FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights); + return ERROR_CALL_NOT_IMPLEMENTED; + +} + +/****************************************************************************** + * GetAuditedPermissionsFromAclW [ADVAPI32.@] + */ +DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCESS_MASK pSuccessfulAuditedRights, + PACCESS_MASK pFailedAuditRights) +{ + FIXME("%p %p %p %p\n",pacl, pTrustee, pSuccessfulAuditedRights, pFailedAuditRights); + return ERROR_CALL_NOT_IMPLEMENTED; + +} /****************************************************************************** * ParseAclStringFlags diff --git a/dlls/advapi32/tests/lsa.c b/dlls/advapi32/tests/lsa.c index 4035416cdc5..7f53907d75d 100644 --- a/dlls/advapi32/tests/lsa.c +++ b/dlls/advapi32/tests/lsa.c @@ -95,7 +95,6 @@ static void test_lsa(void) status = pLsaQueryInformationPolicy(handle, PolicyPrimaryDomainInformation, (PVOID*)&primary_domain_info); ok(status == STATUS_SUCCESS, "LsaQueryInformationPolicy(PolicyPrimaryDomainInformation) failed, returned 0x%08x\n", status); if (status == STATUS_SUCCESS) { - ok(primary_domain_info->Sid==0,"Sid should be NULL on the local computer\n"); if (primary_domain_info->Sid) { LPSTR strsid; if (pConvertSidToStringSidA(primary_domain_info->Sid, &strsid)) @@ -115,6 +114,8 @@ static void test_lsa(void) else trace("invalid sid\n"); } + else + trace("Running on a standalone system.\n"); pLsaFreeMemory((LPVOID)primary_domain_info); } @@ -129,8 +130,6 @@ static void test_lsa(void) ok(status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER, "LsaQueryInformationPolicy(PolicyDnsDomainInformation) failed, returned 0x%08x\n", status); if (status == STATUS_SUCCESS) { - ok(IsEqualGUID(&dns_domain_info->DomainGuid, &GUID_NULL), "DomainGUID should be GUID_NULL on local computer\n"); - ok(dns_domain_info->Sid==0,"Sid should be NULL on the local computer\n"); if (dns_domain_info->Sid || !IsEqualGUID(&dns_domain_info->DomainGuid, &GUID_NULL)) { LPSTR strsid = NULL; LPSTR name = NULL; @@ -169,6 +168,8 @@ static void test_lsa(void) LocalFree( guidstr ); LocalFree( strsid ); } + else + trace("Running on a standalone system.\n"); pLsaFreeMemory((LPVOID)dns_domain_info); } diff --git a/dlls/advpack/advpack.c b/dlls/advpack/advpack.c index 6c26e51083e..112d38ab438 100644 --- a/dlls/advpack/advpack.c +++ b/dlls/advpack/advpack.c @@ -70,7 +70,7 @@ static void get_dest_dir(HINF hInf, PCWSTR pszSection, PWSTR pszBuffer, DWORD dw INFCONTEXT context; WCHAR key[MAX_PATH + 2], value[MAX_PATH + 2]; WCHAR prefix[PREFIX_LEN + 2]; - HKEY root, subkey; + HKEY root, subkey = 0; DWORD size; static const WCHAR hklm[] = {'H','K','L','M',0}; @@ -102,7 +102,7 @@ static void get_dest_dir(HINF hInf, PCWSTR pszSection, PWSTR pszBuffer, DWORD dw strip_quotes(pszBuffer, &size); } - RegCloseKey(subkey); + if (subkey) RegCloseKey(subkey); } /* loads the LDIDs specified in the install section of an INF */ diff --git a/dlls/avifil32/api.c b/dlls/avifil32/api.c index b7b21b93de4..12eb1b7c21f 100644 --- a/dlls/avifil32/api.c +++ b/dlls/avifil32/api.c @@ -1524,7 +1524,7 @@ HRESULT WINAPI AVISaveOptionsFree(INT nStreams,LPAVICOMPRESSOPTIONS*ppOptions) if (nStreams < 0 || ppOptions == NULL) return AVIERR_BADPARAM; - for (; nStreams > 0; nStreams--) { + for (nStreams--; nStreams >= 0; nStreams--) { if (ppOptions[nStreams] != NULL) { ppOptions[nStreams]->dwFlags &= ~AVICOMPRESSF_VALID; diff --git a/dlls/comctl32/ipaddress.c b/dlls/comctl32/ipaddress.c index a9e980b462b..c29406fd186 100644 --- a/dlls/comctl32/ipaddress.c +++ b/dlls/comctl32/ipaddress.c @@ -170,6 +170,8 @@ static LRESULT IPADDRESS_Create (HWND hwnd, const CREATESTRUCTA *lpCreate) IPADDRESS_INFO *infoPtr; RECT rcClient, edit; int i, fieldsize; + HFONT hFont, hSysFont; + LOGFONTW logFont, logSysFont; TRACE("\n"); @@ -191,6 +193,12 @@ static LRESULT IPADDRESS_Create (HWND hwnd, const CREATESTRUCTA *lpCreate) infoPtr->Enabled = TRUE; infoPtr->Notify = lpCreate->hwndParent; + hSysFont = (HFONT) GetStockObject(ANSI_VAR_FONT); + GetObjectW(hSysFont, sizeof(LOGFONTW), &logSysFont); + SystemParametersInfoW(SPI_GETICONTITLELOGFONT, 0, &logFont, 0); + strcpyW(logFont.lfFaceName, logSysFont.lfFaceName); + hFont = CreateFontIndirectW(&logFont); + for (i = 0; i < 4; i++) { IPPART_INFO* part = &infoPtr->Part[i]; @@ -203,6 +211,7 @@ static LRESULT IPADDRESS_Create (HWND hwnd, const CREATESTRUCTA *lpCreate) edit.left, edit.top, edit.right - edit.left, edit.bottom - edit.top, hwnd, (HMENU) 1, (HINSTANCE)GetWindowLongPtrW(hwnd, GWLP_HINSTANCE), NULL); + SendMessageW(part->EditHwnd, WM_SETFONT, (WPARAM) hFont, FALSE); SetPropW(part->EditHwnd, IP_SUBCLASS_PROP, hwnd); part->OrigProc = (WNDPROC) SetWindowLongPtrW (part->EditHwnd, GWLP_WNDPROC, diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c index ce909fe3259..6b16a7bbab7 100644 --- a/dlls/comctl32/listview.c +++ b/dlls/comctl32/listview.c @@ -1638,6 +1638,7 @@ static void LISTVIEW_UpdateHeaderSize(const LISTVIEW_INFO *infoPtr, INT nNewScro SetWindowPos(infoPtr->hwndHeader,0, point[0].x,point[0].y,point[1].x,point[1].y, + (infoPtr->dwStyle & LVS_NOCOLUMNHEADER) ? SWP_HIDEWINDOW : SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOACTIVATE); } @@ -5223,6 +5224,9 @@ static BOOL LISTVIEW_GetColumnT(const LISTVIEW_INFO *infoPtr, INT nColumn, LPLVC if (lpColumn->mask & LVCF_ORDER) hdi.mask |= HDI_ORDER; + if (lpColumn->mask & LVCF_SUBITEM) + hdi.mask |= HDI_LPARAM; + if (!SendMessageW(infoPtr->hwndHeader, isW ? HDM_GETITEMW : HDM_GETITEMA, nColumn, (LPARAM)&hdi)) return FALSE; if (lpColumn->mask & LVCF_FMT) @@ -5237,6 +5241,9 @@ static BOOL LISTVIEW_GetColumnT(const LISTVIEW_INFO *infoPtr, INT nColumn, LPLVC if (lpColumn->mask & LVCF_ORDER) lpColumn->iOrder = hdi.iOrder; + if (lpColumn->mask & LVCF_SUBITEM) + lpColumn->iSubItem = hdi.lParam; + return TRUE; } @@ -7992,6 +7999,7 @@ static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) { LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongPtrW(hwnd, 0); UINT uView = lpcs->style & LVS_TYPEMASK; + DWORD dFlags = WS_CHILD | HDS_HORZ | HDS_FULLDRAG | HDS_DRAGDROP; TRACE("(lpcs=%p)\n", lpcs); @@ -7999,9 +8007,12 @@ static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) infoPtr->notifyFormat = SendMessageW(infoPtr->hwndNotify, WM_NOTIFYFORMAT, (WPARAM)infoPtr->hwndSelf, (LPARAM)NF_QUERY); + /* setup creation flags */ + dFlags |= (LVS_NOSORTHEADER & lpcs->style) ? 0 : HDS_BUTTONS; + dFlags |= (LVS_NOCOLUMNHEADER & lpcs->style) ? HDS_HIDDEN : 0; + /* create header */ - infoPtr->hwndHeader = CreateWindowW(WC_HEADERW, NULL, - WS_CHILD | HDS_HORZ | HDS_FULLDRAG | (DWORD)((LVS_NOSORTHEADER & lpcs->style)?0:HDS_BUTTONS), + infoPtr->hwndHeader = CreateWindowW(WC_HEADERW, NULL, dFlags, 0, 0, 0, 0, hwnd, NULL, lpcs->hInstance, NULL); if (!infoPtr->hwndHeader) return -1; @@ -8021,12 +8032,8 @@ static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) { ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL); } - else - { - /* set HDS_HIDDEN flag to hide the header bar */ - SetWindowLongW(infoPtr->hwndHeader, GWL_STYLE, - GetWindowLongW(infoPtr->hwndHeader, GWL_STYLE) | HDS_HIDDEN); - } + LISTVIEW_UpdateSize(infoPtr); + LISTVIEW_UpdateScroll(infoPtr); } OpenThemeData(hwnd, themeClass); @@ -9260,7 +9267,11 @@ static LRESULT LISTVIEW_SetFont(LISTVIEW_INFO *infoPtr, HFONT hFont, WORD fRedra LISTVIEW_SaveTextMetrics(infoPtr); if ((infoPtr->dwStyle & LVS_TYPEMASK) == LVS_REPORT) + { SendMessageW(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(fRedraw, 0)); + LISTVIEW_UpdateSize(infoPtr); + LISTVIEW_UpdateScroll(infoPtr); + } if (fRedraw) LISTVIEW_InvalidateList(infoPtr); @@ -9371,7 +9382,7 @@ static void LISTVIEW_UpdateSize(LISTVIEW_INFO *infoPtr) infoPtr->rcList.bottom -= GetSystemMetrics(SM_CYHSCROLL); infoPtr->rcList.bottom = max (infoPtr->rcList.bottom - 2, 0); } - else if (uView == LVS_REPORT && !(infoPtr->dwStyle & LVS_NOCOLUMNHEADER)) + else if (uView == LVS_REPORT) { HDLAYOUT hl; WINDOWPOS wp; @@ -9380,7 +9391,9 @@ static void LISTVIEW_UpdateSize(LISTVIEW_INFO *infoPtr) hl.pwpos = ℘ SendMessageW( infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl ); TRACE(" wp.flags=0x%08x, wp=%d,%d (%dx%d)\n", wp.flags, wp.x, wp.y, wp.cx, wp.cy); - SetWindowPos(wp.hwnd, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags); + SetWindowPos(wp.hwnd, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, + wp.flags | ((infoPtr->dwStyle & LVS_NOCOLUMNHEADER) + ? SWP_HIDEWINDOW : SWP_SHOWWINDOW)); TRACE(" after SWP wp=%d,%d (%dx%d)\n", wp.x, wp.y, wp.cx, wp.cy); infoPtr->rcList.top = max(wp.cy, 0); @@ -9407,6 +9420,7 @@ static INT LISTVIEW_StyleChanged(LISTVIEW_INFO *infoPtr, WPARAM wStyleType, { UINT uNewView = lpss->styleNew & LVS_TYPEMASK; UINT uOldView = lpss->styleOld & LVS_TYPEMASK; + UINT style; TRACE("(styletype=%lx, styleOld=0x%08x, styleNew=0x%08x)\n", wStyleType, lpss->styleOld, lpss->styleNew); @@ -9459,15 +9473,35 @@ static INT LISTVIEW_StyleChanged(LISTVIEW_INFO *infoPtr, WPARAM wStyleType, hl.prc = &infoPtr->rcList; hl.pwpos = ℘ SendMessageW( infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl ); - SetWindowPos(infoPtr->hwndHeader, infoPtr->hwndSelf, wp.x, wp.y, wp.cx, wp.cy, wp.flags); + SetWindowPos(infoPtr->hwndHeader, infoPtr->hwndSelf, wp.x, wp.y, wp.cx, wp.cy, + wp.flags | ((infoPtr->dwStyle & LVS_NOCOLUMNHEADER) + ? SWP_HIDEWINDOW : SWP_SHOWWINDOW)); } LISTVIEW_UpdateItemSize(infoPtr); } if (uNewView == LVS_REPORT) - ShowWindow(infoPtr->hwndHeader, (lpss->styleNew & LVS_NOCOLUMNHEADER) ? SW_HIDE : SW_SHOWNORMAL); - + { + if ((lpss->styleOld ^ lpss->styleNew) & LVS_NOCOLUMNHEADER) + { + if (lpss->styleNew & LVS_NOCOLUMNHEADER) + { + /* Turn off the header control */ + style = GetWindowLongW(infoPtr->hwndHeader, GWL_STYLE); + TRACE("Hide header control, was 0x%08x\n", style); + SetWindowLongW(infoPtr->hwndHeader, GWL_STYLE, style | HDS_HIDDEN); + } else { + /* Turn on the header control */ + if ((style = GetWindowLongW(infoPtr->hwndHeader, GWL_STYLE)) & HDS_HIDDEN) + { + TRACE("Show header control, was 0x%08x\n", style); + SetWindowLongW(infoPtr->hwndHeader, GWL_STYLE, (style & ~HDS_HIDDEN) | WS_VISIBLE); + } + } + } + } + if ( (uNewView == LVS_ICON || uNewView == LVS_SMALLICON) && (uNewView != uOldView || ((lpss->styleNew ^ lpss->styleOld) & LVS_ALIGNMASK)) ) LISTVIEW_Arrange(infoPtr, LVA_DEFAULT); diff --git a/dlls/comctl32/tooltips.c b/dlls/comctl32/tooltips.c index 48d775715a1..fb2191bc0a8 100644 --- a/dlls/comctl32/tooltips.c +++ b/dlls/comctl32/tooltips.c @@ -883,7 +883,7 @@ static INT TOOLTIPS_GetToolFromInfoA (const TOOLTIPS_INFO *infoPtr, const TTTOOLINFOA *lpToolInfo) { TTTOOL_INFO *toolPtr; - INT nTool; + UINT nTool; for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { toolPtr = &infoPtr->tools[nTool]; @@ -910,7 +910,7 @@ static INT TOOLTIPS_GetToolFromInfoW (const TOOLTIPS_INFO *infoPtr, const TTTOOLINFOW *lpToolInfo) { TTTOOL_INFO *toolPtr; - INT nTool; + UINT nTool; for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { toolPtr = &infoPtr->tools[nTool]; @@ -937,7 +937,7 @@ static INT TOOLTIPS_GetToolFromPoint (const TOOLTIPS_INFO *infoPtr, HWND hwnd, const POINT *lpPt) { TTTOOL_INFO *toolPtr; - INT nTool; + UINT nTool; for (nTool = 0; nTool < infoPtr->uNumTools; nTool++) { toolPtr = &infoPtr->tools[nTool]; diff --git a/dlls/comdlg32/tests/filedlg.c b/dlls/comdlg32/tests/filedlg.c index abceb15c6a4..bd7689fa187 100644 --- a/dlls/comdlg32/tests/filedlg.c +++ b/dlls/comdlg32/tests/filedlg.c @@ -86,6 +86,24 @@ static void test_DialogCancel(void) ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n", CDERR_INITIALIZATION, CommDlgExtendedError()); + result = GetSaveFileNameA(&ofn); + ok(0 == result, "expected %d, got %d\n", 0, result); + ok(0 == CommDlgExtendedError(), "expected %d, got %d\n", 0, + CommDlgExtendedError()); + + PrintDlgA(NULL); + ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n", + CDERR_INITIALIZATION, CommDlgExtendedError()); + + /* Before passing the ofn to Unicode functions, remove the ANSI strings */ + ofn.lpstrFilter = NULL; + ofn.lpstrInitialDir = NULL; + ofn.lpstrDefExt = NULL; + + PrintDlgA(NULL); + ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n", + CDERR_INITIALIZATION, CommDlgExtendedError()); + SetLastError(0xdeadbeef); result = GetOpenFileNameW((LPOPENFILENAMEW) &ofn); if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) @@ -97,19 +115,6 @@ static void test_DialogCancel(void) CommDlgExtendedError()); } - PrintDlgA(NULL); - ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n", - CDERR_INITIALIZATION, CommDlgExtendedError()); - - result = GetSaveFileNameA(&ofn); - ok(0 == result, "expected %d, got %d\n", 0, result); - ok(0 == CommDlgExtendedError(), "expected %d, got %d\n", 0, - CommDlgExtendedError()); - - PrintDlgA(NULL); - ok(CDERR_INITIALIZATION == CommDlgExtendedError(), "expected %d, got %d\n", - CDERR_INITIALIZATION, CommDlgExtendedError()); - SetLastError(0xdeadbeef); result = GetSaveFileNameW((LPOPENFILENAMEW) &ofn); if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) diff --git a/dlls/d3d8/d3d8_main.c b/dlls/d3d8/d3d8_main.c index 63cb47204d5..56de60daba7 100644 --- a/dlls/d3d8/d3d8_main.c +++ b/dlls/d3d8/d3d8_main.c @@ -58,6 +58,11 @@ IDirect3D8* WINAPI Direct3DCreate8(UINT SDKVersion) { TRACE("Created Direct3D object @ %p, WineObj @ %p\n", object, object->WineD3D); LeaveCriticalSection(&d3d8_cs); + if (!object->WineD3D) + { + HeapFree( GetProcessHeap(), 0, object ); + object = NULL; + } return (IDirect3D8*) object; } diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c index 4c15560c5fe..5dbc125512b 100644 --- a/dlls/d3d8/tests/visual.c +++ b/dlls/d3d8/tests/visual.c @@ -746,7 +746,7 @@ static void alpha_test(IDirect3DDevice8 *device) HRESULT hr; IDirect3DTexture8 *offscreenTexture; IDirect3DSurface8 *backbuffer = NULL, *offscreen = NULL, *depthstencil = NULL; - DWORD color, red, green, blue; + DWORD color; struct vertex quad1[] = { @@ -870,32 +870,20 @@ static void alpha_test(IDirect3DDevice8 *device) IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); color = getPixelColor(device, 160, 360); - red = (color & 0x00ff0000) >> 16; - green = (color & 0x0000ff00) >> 8; - blue = (color & 0x000000ff); - ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00, + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1), "SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color); color = getPixelColor(device, 160, 120); - red = (color & 0x00ff0000) >> 16; - green = (color & 0x0000ff00) >> 8; - blue = (color & 0x000000ff); - ok(red >= 0x7e && red <= 0x81 && green == 0x00 && blue >= 0x7e && blue <= 0x81, - "DSTALPHA on frame buffer returned color %08x, expected 0x00ff0000\n", color); + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x00, 0x80), 2), + "DSTALPHA on frame buffer returned color %08x, expected 0x007f0080\n", color); color = getPixelColor(device, 480, 360); - red = (color & 0x00ff0000) >> 16; - green = (color & 0x0000ff00) >> 8; - blue = (color & 0x000000ff); - ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00, - "SRCALPHA on texture returned color %08x, expected bar\n", color); + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1), + "SRCALPHA on texture returned color %08x, expected 0x00bf4000\n", color); color = getPixelColor(device, 480, 120); - red = (color & 0x00ff0000) >> 16; - green = (color & 0x0000ff00) >> 8; - blue = (color & 0x000000ff); - ok(red == 0x00 && green == 0x00 && blue >= 0xfe && blue <= 0xff , - "DSTALPHA on texture returned color %08x, expected foo\n", color); + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff), 1), + "DSTALPHA on texture returned color %08x, expected 0x000000ff\n", color); out: /* restore things */ @@ -1272,7 +1260,7 @@ static void texop_test(IDirect3DDevice8 *device) ok(SUCCEEDED(hr), "Present failed with 0x%08x (%s)\n", hr, DXGetErrorString8(hr)); color = getPixelColor(device, 320, 240); - ok(color_match(color, test_data[i].result, 1), "Operation %s returned color 0x%08x, expected 0x%08x\n", + ok(color_match(color, test_data[i].result, 3), "Operation %s returned color 0x%08x, expected 0x%08x\n", test_data[i].name, color, test_data[i].result); } diff --git a/dlls/d3d9/d3d9_main.c b/dlls/d3d9/d3d9_main.c index 69ad9c845dd..a93c1223605 100644 --- a/dlls/d3d9/d3d9_main.c +++ b/dlls/d3d9/d3d9_main.c @@ -53,6 +53,11 @@ IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion) { TRACE("SDKVersion = %x, Created Direct3D object @ %p, WineObj @ %p\n", SDKVersion, object, object->WineD3D); + if (!object->WineD3D) + { + HeapFree( GetProcessHeap(), 0, object ); + object = NULL; + } return (IDirect3D9*) object; } diff --git a/dlls/d3d9/tests/d3d9ex.c b/dlls/d3d9/tests/d3d9ex.c index 6df4c45dd9c..0d80abbd602 100644 --- a/dlls/d3d9/tests/d3d9ex.c +++ b/dlls/d3d9/tests/d3d9ex.c @@ -58,6 +58,9 @@ static void test_qi_base_to_ex(void) HWND window = create_window(); D3DPRESENT_PARAMETERS present_parameters; + ok( d3d9 != NULL, "Failed to create D3D9 object\n" ); + if (!d3d9) return; + hr = IDirect3D9_QueryInterface(d3d9, &IID_IDirect3D9Ex, (void **) &d3d9ex); ok(hr == E_NOINTERFACE, "IDirect3D9::QueryInterface for IID_IDirect3D9Ex returned %s, expected E_NOINTERFACE\n", diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index a328123ef87..611a589963c 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -1463,9 +1463,7 @@ static void fog_with_shader_test(IDirect3DDevice9 *device) /* As the red and green component are the result of blending use 5% tolerance on the expected value */ color = getPixelColor(device, 128, 240); - ok((unsigned char)(color) == ((unsigned char)test_data[i].color[j]) - && abs( ((unsigned char)(color>>8)) - (unsigned char)(test_data[i].color[j]>>8) ) < 13 - && abs( ((unsigned char)(color>>16)) - (unsigned char)(test_data[i].color[j]>>16) ) < 13, + ok(color_match(color, test_data[i].color[j], 13), "fog vs%i ps%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%\n", test_data[i].vshader, test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]); } @@ -4893,6 +4891,9 @@ static void cnd_test(IDirect3DDevice9 *device) hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr)); + hr = IDirect3DDevice9_SetPixelShader(device, NULL); + ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr)); + /* This is the 1.4 test. The coissue doesn't change the behavior here, but keep in mind * that we swapped the values in c1 and c2 to make the other tests return some color */ @@ -6656,7 +6657,7 @@ static void alpha_test(IDirect3DDevice9 *device) HRESULT hr; IDirect3DTexture9 *offscreenTexture; IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL; - DWORD color, red, green, blue; + DWORD color; struct vertex quad1[] = { @@ -6778,32 +6779,20 @@ static void alpha_test(IDirect3DDevice9 *device) IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); color = getPixelColor(device, 160, 360); - red = (color & 0x00ff0000) >> 16; - green = (color & 0x0000ff00) >> 8; - blue = (color & 0x000000ff); - ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00, + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1), "SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color); color = getPixelColor(device, 160, 120); - red = (color & 0x00ff0000) >> 16; - green = (color & 0x0000ff00) >> 8; - blue = (color & 0x000000ff); - ok(red >= 0x7e && red <= 0x81 && green == 0x00 && blue >= 0x7e && blue <= 0x81, - "DSTALPHA on frame buffer returned color %08x, expected 0x00ff0000\n", color); + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x00, 0x80), 2), + "DSTALPHA on frame buffer returned color %08x, expected 0x007f0080\n", color); color = getPixelColor(device, 480, 360); - red = (color & 0x00ff0000) >> 16; - green = (color & 0x0000ff00) >> 8; - blue = (color & 0x000000ff); - ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00, - "SRCALPHA on texture returned color %08x, expected bar\n", color); + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1), + "SRCALPHA on texture returned color %08x, expected 0x00bf4000\n", color); color = getPixelColor(device, 480, 120); - red = (color & 0x00ff0000) >> 16; - green = (color & 0x0000ff00) >> 8; - blue = (color & 0x000000ff); - ok(red == 0x00 && green == 0x00 && blue >= 0xfe && blue <= 0xff , - "DSTALPHA on texture returned color %08x, expected 0x00800080\n", color); + ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff), 1), + "DSTALPHA on texture returned color %08x, expected 0x000000ff\n", color); out: /* restore things */ @@ -9216,7 +9205,7 @@ static void texop_test(IDirect3DDevice9 *device) ok(SUCCEEDED(hr), "Present failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr)); color = getPixelColor(device, 320, 240); - ok(color_match(color, test_data[i].result, 1), "Operation %s returned color 0x%08x, expected 0x%08x\n", + ok(color_match(color, test_data[i].result, 3), "Operation %s returned color 0x%08x, expected 0x%08x\n", test_data[i].name, color, test_data[i].result); } diff --git a/dlls/d3dx9_24/Makefile.in b/dlls/d3dx9_24/Makefile.in index 3d28377f5a9..7fadf575897 100644 --- a/dlls/d3dx9_24/Makefile.in +++ b/dlls/d3dx9_24/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_24_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_24/version.rc similarity index 70% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_24/version.rc index b00066de518..8deff200d3e 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_24/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,5,132,0 +#define WINE_FILEVERSION_STR "9.5.132.0" +#define WINE_PRODUCTVERSION 9,5,132,0 +#define WINE_PRODUCTVERSION_STR "9.5.132.0" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_25/Makefile.in b/dlls/d3dx9_25/Makefile.in index 3b2dd122d82..730817a13b2 100644 --- a/dlls/d3dx9_25/Makefile.in +++ b/dlls/d3dx9_25/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_25_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_25/version.rc similarity index 70% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_25/version.rc index b00066de518..922770c5db3 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_25/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,6,168,0 +#define WINE_FILEVERSION_STR "9.6.168.0" +#define WINE_PRODUCTVERSION 9,6,168,0 +#define WINE_PRODUCTVERSION_STR "9.6.168.0" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_26/Makefile.in b/dlls/d3dx9_26/Makefile.in index 76de9f0fcd3..8852fb8b3b6 100644 --- a/dlls/d3dx9_26/Makefile.in +++ b/dlls/d3dx9_26/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_26_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_26/version.rc similarity index 70% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_26/version.rc index b00066de518..56edd133534 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_26/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,7,239,0 +#define WINE_FILEVERSION_STR "9.7.239.0" +#define WINE_PRODUCTVERSION 9,7,239,0 +#define WINE_PRODUCTVERSION_STR "9.7.239.0" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_27/Makefile.in b/dlls/d3dx9_27/Makefile.in index 9f47af7a7e7..064fdd34293 100644 --- a/dlls/d3dx9_27/Makefile.in +++ b/dlls/d3dx9_27/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_27_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_27/version.rc similarity index 70% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_27/version.rc index b00066de518..82be05ef485 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_27/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,8,299,0 +#define WINE_FILEVERSION_STR "9.8.299.0" +#define WINE_PRODUCTVERSION 9,8,299,0 +#define WINE_PRODUCTVERSION_STR "9.8.299.0" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_28/Makefile.in b/dlls/d3dx9_28/Makefile.in index 8b494034a3a..01bc95d0cbb 100644 --- a/dlls/d3dx9_28/Makefile.in +++ b/dlls/d3dx9_28/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_28_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_28/version.rc similarity index 70% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_28/version.rc index b00066de518..0f61f70880e 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_28/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,10,455,0 +#define WINE_FILEVERSION_STR "9.10.455.0" +#define WINE_PRODUCTVERSION 9,10,455,0 +#define WINE_PRODUCTVERSION_STR "9.10.455.0" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_29/Makefile.in b/dlls/d3dx9_29/Makefile.in index 39e6724adea..a3871d29e97 100644 --- a/dlls/d3dx9_29/Makefile.in +++ b/dlls/d3dx9_29/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_29_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_29/version.rc similarity index 70% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_29/version.rc index b00066de518..f6f7b1351d9 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_29/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,11,519,0 +#define WINE_FILEVERSION_STR "9.11.519.0" +#define WINE_PRODUCTVERSION 9,11,519,0 +#define WINE_PRODUCTVERSION_STR "9.11.519.0" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_30/Makefile.in b/dlls/d3dx9_30/Makefile.in index 43c4ae0e267..62a054ef90c 100644 --- a/dlls/d3dx9_30/Makefile.in +++ b/dlls/d3dx9_30/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_30_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_30/version.rc similarity index 70% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_30/version.rc index b00066de518..b10286e6b81 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_30/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,12,589,0 +#define WINE_FILEVERSION_STR "9.12.589.0" +#define WINE_PRODUCTVERSION 9,12,589,0 +#define WINE_PRODUCTVERSION_STR "9.12.589.0" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_31/Makefile.in b/dlls/d3dx9_31/Makefile.in index fc2482fd24f..daf84d0c4b7 100644 --- a/dlls/d3dx9_31/Makefile.in +++ b/dlls/d3dx9_31/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_31_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_31/version.rc similarity index 70% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_31/version.rc index b00066de518..eb974540014 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_31/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,15,779,0 +#define WINE_FILEVERSION_STR "9.15.779.0" +#define WINE_PRODUCTVERSION 9,15,779,0 +#define WINE_PRODUCTVERSION_STR "9.15.779.0" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_32/Makefile.in b/dlls/d3dx9_32/Makefile.in index 1b47cd1da8a..d3e98d30cb0 100644 --- a/dlls/d3dx9_32/Makefile.in +++ b/dlls/d3dx9_32/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_32_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_32/version.rc similarity index 70% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_32/version.rc index b00066de518..330f8be684f 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_32/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,16,843,0 +#define WINE_FILEVERSION_STR "9.16.843.0" +#define WINE_PRODUCTVERSION 9,16,843,0 +#define WINE_PRODUCTVERSION_STR "9.16.843.0" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_33/Makefile.in b/dlls/d3dx9_33/Makefile.in index 1bb4b11d78b..6761464ea46 100644 --- a/dlls/d3dx9_33/Makefile.in +++ b/dlls/d3dx9_33/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_33_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_33/version.rc similarity index 70% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_33/version.rc index b00066de518..06eba53b470 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_33/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,18,904,15 +#define WINE_FILEVERSION_STR "9.18.904.15" +#define WINE_PRODUCTVERSION 9,18,904,15 +#define WINE_PRODUCTVERSION_STR "9.18.904.15" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_34/Makefile.in b/dlls/d3dx9_34/Makefile.in index 6dd7837272f..c38c83c6acf 100644 --- a/dlls/d3dx9_34/Makefile.in +++ b/dlls/d3dx9_34/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_34_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_34/version.rc similarity index 70% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_34/version.rc index b00066de518..5045d8fa852 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_34/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,19,949,46 +#define WINE_FILEVERSION_STR "9.19.949.46" +#define WINE_PRODUCTVERSION 9,19,949,46 +#define WINE_PRODUCTVERSION_STR "9.19.949.46" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_35/Makefile.in b/dlls/d3dx9_35/Makefile.in index 88b0116d70e..19094d2f841 100644 --- a/dlls/d3dx9_35/Makefile.in +++ b/dlls/d3dx9_35/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_35_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_35/version.rc similarity index 69% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_35/version.rc index b00066de518..6ffaafb4b47 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_35/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,19,949,1104 +#define WINE_FILEVERSION_STR "9.19.949.1104" +#define WINE_PRODUCTVERSION 9,19,949,1104 +#define WINE_PRODUCTVERSION_STR "9.19.949.1104" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_36/Makefile.in b/dlls/d3dx9_36/Makefile.in index 2ed85ea4140..4c3f09ad03a 100644 --- a/dlls/d3dx9_36/Makefile.in +++ b/dlls/d3dx9_36/Makefile.in @@ -11,6 +11,8 @@ C_SRCS = \ font.c \ math.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_36/version.rc similarity index 69% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_36/version.rc index b00066de518..8ca195d5c66 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_36/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,19,949,2111 +#define WINE_FILEVERSION_STR "9.19.949.2111" +#define WINE_PRODUCTVERSION 9,19,949,2111 +#define WINE_PRODUCTVERSION_STR "9.19.949.2111" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/d3dx9_37/Makefile.in b/dlls/d3dx9_37/Makefile.in index 6de5cb4d9b8..c4e3e222e89 100644 --- a/dlls/d3dx9_37/Makefile.in +++ b/dlls/d3dx9_37/Makefile.in @@ -8,6 +8,8 @@ IMPORTS = d3d9 kernel32 C_SRCS = \ d3dx9_37_main.c +RC_SRCS = version.rc + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/d3dx9_37/version.rc similarity index 69% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/d3dx9_37/version.rc index b00066de518..aeb99d2cf9c 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/d3dx9_37/version.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Louis Lenders * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H +#define WINE_FILEDESCRIPTION_STR "Wine D3DX9" +#define WINE_FILENAME_STR "d3dx9.dll" +#define WINE_FILEVERSION 9,22,949,2248 +#define WINE_FILEVERSION_STR "9.22.949.2248" +#define WINE_PRODUCTVERSION 9,22,949,2248 +#define WINE_PRODUCTVERSION_STR "9.22.949.2248" -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/wine_common_ver.rc" diff --git a/dlls/dbghelp/dbghelp.spec b/dlls/dbghelp/dbghelp.spec index d29b8808f26..b95a9e728bf 100644 --- a/dlls/dbghelp/dbghelp.spec +++ b/dlls/dbghelp/dbghelp.spec @@ -48,7 +48,7 @@ @ stdcall SymEnumerateModules64(long ptr ptr) @ stdcall SymEnumerateModulesW64(long ptr ptr) @ stdcall SymEnumerateSymbols(long long ptr ptr) -@ stub SymEnumerateSymbols64 +@ stdcall SymEnumerateSymbols64(long double ptr ptr) @ stub SymEnumerateSymbolsW @ stub SymEnumerateSymbolsW64 @ stub SymFindDebugInfoFile diff --git a/dlls/dbghelp/stabs.c b/dlls/dbghelp/stabs.c index d5506337f7d..9955b7eac62 100644 --- a/dlls/dbghelp/stabs.c +++ b/dlls/dbghelp/stabs.c @@ -1003,7 +1003,7 @@ static int stabs_pts_read_type_def(struct ParseTypedefData* ptd, const char* typ *stabs_find_ref(filenr1, subnr1) = *ret_dt = new_dt; - TRACE("Adding (%ld,%ld) %s\n", filenr1, subnr1, typename); + TRACE("Adding (%ld,%ld) %s\n", filenr1, subnr1, debugstr_a(typename)); return 0; } diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 1d7edb8463d..f4f2d11644a 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -1055,6 +1055,33 @@ BOOL WINAPI SymEnumerateSymbols(HANDLE hProcess, DWORD BaseOfDll, return SymEnumSymbols(hProcess, BaseOfDll, NULL, sym_enumerate_cb, &se); } +struct sym_enumerate64 +{ + void* ctx; + PSYM_ENUMSYMBOLS_CALLBACK64 cb; +}; + +static BOOL CALLBACK sym_enumerate_cb64(PSYMBOL_INFO syminfo, ULONG size, void* ctx) +{ + struct sym_enumerate64* se = (struct sym_enumerate64*)ctx; + return (se->cb)(syminfo->Name, syminfo->Address, syminfo->Size, se->ctx); +} + +/*********************************************************************** + * SymEnumerateSymbols64 (DBGHELP.@) + */ +BOOL WINAPI SymEnumerateSymbols64(HANDLE hProcess, DWORD64 BaseOfDll, + PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback, + PVOID UserContext) +{ + struct sym_enumerate64 se; + + se.ctx = UserContext; + se.cb = EnumSymbolsCallback; + + return SymEnumSymbols(hProcess, BaseOfDll, NULL, sym_enumerate_cb64, &se); +} + /****************************************************************** * SymFromAddr (DBGHELP.@) * diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index ab78c4b60d9..9a473190591 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -524,8 +524,6 @@ IDirectDrawImpl_SetCooperativeLevel(IDirectDraw7 *iface, WARN("(%p) Unhandled flag DDSCL_ALLOWMODEX, harmless\n", This); if(cooplevel & DDSCL_FPUSETUP) WARN("(%p) Unhandled flag DDSCL_FPUSETUP, harmless\n", This); - if(cooplevel & DDSCL_FPUPRESERVE) - WARN("(%p) Unhandled flag DDSCL_FPUPRESERVE, harmless\n", This); /* Store the cooperative_level */ This->cooperative_level |= cooplevel; @@ -3241,6 +3239,12 @@ DirectDrawCreateClipper(DWORD Flags, return CLASS_E_NOAGGREGATION; } + if (!LoadWineD3D()) + { + LeaveCriticalSection(&ddraw_cs); + return DDERR_NODIRECTDRAWSUPPORT; + } + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawClipperImpl)); if (object == NULL) diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index f256c501dbd..bde2baef415 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -358,7 +358,8 @@ struct IDirect3DDeviceImpl }; /* Vtables in various versions */ -const IDirect3DDevice7Vtbl IDirect3DDevice7_Vtbl; +const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl; +const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl; const IDirect3DDevice3Vtbl IDirect3DDevice3_Vtbl; const IDirect3DDevice2Vtbl IDirect3DDevice2_Vtbl; const IDirect3DDeviceVtbl IDirect3DDevice1_Vtbl; @@ -644,6 +645,9 @@ void DDRAW_dump_cooperativelevel(DWORD cooplevel); * IDirect3DExecuteBuffer isn't in WineD3D */ void multiply_matrix(LPD3DMATRIX dest, const D3DMATRIX *src1, const D3DMATRIX *src2); +/* Helper function in main.c */ +BOOL LoadWineD3D(void); + /* Used for generic dumping */ typedef struct { diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 88d54537179..15bb6ca48c1 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -61,6 +61,37 @@ const GUID IID_D3DDEVICE_WineD3D = { { 0xb7,0x98,0xc6,0x8a,0x77,0x2d,0x72,0x2a } }; +static inline void set_fpu_control_word(WORD fpucw) +{ +#if defined(__i386__) && defined(__GNUC__) + __asm__ volatile ("fldcw %0" : : "m" (fpucw)); +#elif defined(__i386__) && defined(_MSC_VER) + __asm fldcw fpucw; +#endif +} + +static inline WORD d3d_fpu_setup(void) +{ + WORD oldcw; + +#if defined(__i386__) && defined(__GNUC__) + __asm__ volatile ("fnstcw %0" : "=m" (oldcw)); +#elif defined(__i386__) && defined(_MSC_VER) + __asm fnstcw oldcw; +#else + static BOOL warned = FALSE; + if(!warned) + { + FIXME("FPUPRESERVE not implemented for this platform / compiler\n"); + warned = TRUE; + } +#endif + + set_fpu_control_word(0x37f); + + return oldcw; +} + /***************************************************************************** * IUnknown Methods. Common for Version 1, 2, 3 and 7 *****************************************************************************/ @@ -481,7 +512,7 @@ IDirect3DDeviceImpl_1_Initialize(IDirect3DDevice *iface, * D3DERR_* if a problem occurs. See WineD3D * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface, D3DDEVICEDESC7 *Desc) { @@ -493,6 +524,26 @@ IDirect3DDeviceImpl_7_GetCaps(IDirect3DDevice7 *iface, return IDirect3DImpl_GetCaps(This->ddraw->wineD3D, &OldDesc, Desc); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetCaps_FPUSetup(IDirect3DDevice7 *iface, + D3DDEVICEDESC7 *Desc) +{ + return IDirect3DDeviceImpl_7_GetCaps(iface, Desc); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetCaps_FPUPreserve(IDirect3DDevice7 *iface, + D3DDEVICEDESC7 *Desc) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_GetCaps(iface, Desc); + set_fpu_control_word(old_fpucw); + + return hr; +} /***************************************************************************** * IDirect3DDevice3::GetCaps * @@ -1106,7 +1157,7 @@ IDirect3DDeviceImpl_1_GetPickRecords(IDirect3DDevice *iface, * DDERR_INVALIDPARAMS if Callback == NULL * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface, LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg) @@ -1212,6 +1263,29 @@ IDirect3DDeviceImpl_7_EnumTextureFormats(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup(IDirect3DDevice7 *iface, + LPD3DENUMPIXELFORMATSCALLBACK Callback, + void *Arg) +{ + return IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve(IDirect3DDevice7 *iface, + LPD3DENUMPIXELFORMATSCALLBACK Callback, + void *Arg) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_EnumTextureFormats(iface, Callback, Arg); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats(IDirect3DDevice3 *iface, LPD3DENUMPIXELFORMATSCALLBACK Callback, void *Arg) @@ -1544,7 +1618,7 @@ IDirect3DDeviceImpl_1_DeleteMatrix(IDirect3DDevice *iface, * started scene). * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); @@ -1559,6 +1633,25 @@ IDirect3DDeviceImpl_7_BeginScene(IDirect3DDevice7 *iface) } static HRESULT WINAPI +IDirect3DDeviceImpl_7_BeginScene_FPUSetup(IDirect3DDevice7 *iface) +{ + return IDirect3DDeviceImpl_7_BeginScene(iface); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_BeginScene_FPUPreserve(IDirect3DDevice7 *iface) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_BeginScene(iface); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_BeginScene(IDirect3DDevice3 *iface) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface); @@ -1596,7 +1689,7 @@ Thunk_IDirect3DDeviceImpl_1_BeginScene(IDirect3DDevice *iface) * that only if the scene was already ended. * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); @@ -1611,6 +1704,25 @@ IDirect3DDeviceImpl_7_EndScene(IDirect3DDevice7 *iface) } static HRESULT WINAPI +IDirect3DDeviceImpl_7_EndScene_FPUSetup(IDirect3DDevice7 *iface) +{ + return IDirect3DDeviceImpl_7_EndScene(iface); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_EndScene_FPUPreserve(IDirect3DDevice7 *iface) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_EndScene(iface); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_EndScene(IDirect3DDevice3 *iface) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface); @@ -1852,7 +1964,7 @@ Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport(IDirect3DDevice2 *iface, * D3D_OK on success, for details see IWineD3DDevice::SetRenderTarget * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface, IDirectDrawSurface7 *NewTarget, DWORD Flags) @@ -1889,6 +2001,29 @@ IDirect3DDeviceImpl_7_SetRenderTarget(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup(IDirect3DDevice7 *iface, + IDirectDrawSurface7 *NewTarget, + DWORD Flags) +{ + return IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve(IDirect3DDevice7 *iface, + IDirectDrawSurface7 *NewTarget, + DWORD Flags) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_SetRenderTarget(iface, NewTarget, Flags); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_SetRenderTarget(IDirect3DDevice3 *iface, IDirectDrawSurface4 *NewRenderTarget, DWORD Flags) @@ -2251,7 +2386,7 @@ Thunk_IDirect3DDeviceImpl_2_End(IDirect3DDevice2 *iface, * DDERR_INVALIDPARAMS if Value == NULL * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface, D3DRENDERSTATETYPE RenderStateType, DWORD *Value) @@ -2335,6 +2470,29 @@ IDirect3DDeviceImpl_7_GetRenderState(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetRenderState_FPUSetup(IDirect3DDevice7 *iface, + D3DRENDERSTATETYPE RenderStateType, + DWORD *Value) +{ + return IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve(IDirect3DDevice7 *iface, + D3DRENDERSTATETYPE RenderStateType, + DWORD *Value) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_GetRenderState(iface, RenderStateType, Value); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI IDirect3DDeviceImpl_3_GetRenderState(IDirect3DDevice3 *iface, D3DRENDERSTATETYPE dwRenderStateType, DWORD *lpdwRenderState) @@ -2494,7 +2652,7 @@ Thunk_IDirect3DDeviceImpl_2_GetRenderState(IDirect3DDevice2 *iface, * for details see IWineD3DDevice::SetRenderState * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface, D3DRENDERSTATETYPE RenderStateType, DWORD Value) @@ -2604,6 +2762,29 @@ IDirect3DDeviceImpl_7_SetRenderState(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetRenderState_FPUSetup(IDirect3DDevice7 *iface, + D3DRENDERSTATETYPE RenderStateType, + DWORD Value) +{ + return IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve(IDirect3DDevice7 *iface, + D3DRENDERSTATETYPE RenderStateType, + DWORD Value) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_SetRenderState(iface, RenderStateType, Value); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI IDirect3DDeviceImpl_3_SetRenderState(IDirect3DDevice3 *iface, D3DRENDERSTATETYPE RenderStateType, DWORD Value) @@ -3034,7 +3215,7 @@ Thunk_IDirect3DDeviceImpl_2_GetLightState(IDirect3DDevice2 *iface, * For details see IWineD3DDevice::SetTransform * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface, D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *Matrix) @@ -3066,6 +3247,29 @@ IDirect3DDeviceImpl_7_SetTransform(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetTransform_FPUSetup(IDirect3DDevice7 *iface, + D3DTRANSFORMSTATETYPE TransformStateType, + D3DMATRIX *Matrix) +{ + return IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetTransform_FPUPreserve(IDirect3DDevice7 *iface, + D3DTRANSFORMSTATETYPE TransformStateType, + D3DMATRIX *Matrix) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_SetTransform(iface, TransformStateType, Matrix); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_SetTransform(IDirect3DDevice3 *iface, D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix) @@ -3106,7 +3310,7 @@ Thunk_IDirect3DDeviceImpl_2_SetTransform(IDirect3DDevice2 *iface, * For details, see IWineD3DDevice::GetTransform * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface, D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *Matrix) @@ -3136,6 +3340,29 @@ IDirect3DDeviceImpl_7_GetTransform(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetTransform_FPUSetup(IDirect3DDevice7 *iface, + D3DTRANSFORMSTATETYPE TransformStateType, + D3DMATRIX *Matrix) +{ + return IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetTransform_FPUPreserve(IDirect3DDevice7 *iface, + D3DTRANSFORMSTATETYPE TransformStateType, + D3DMATRIX *Matrix) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_GetTransform(iface, TransformStateType, Matrix); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_GetTransform(IDirect3DDevice3 *iface, D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix) @@ -3177,7 +3404,7 @@ Thunk_IDirect3DDeviceImpl_2_GetTransform(IDirect3DDevice2 *iface, * For details, see IWineD3DDevice::MultiplyTransform * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface, D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix) @@ -3206,6 +3433,29 @@ IDirect3DDeviceImpl_7_MultiplyTransform(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup(IDirect3DDevice7 *iface, + D3DTRANSFORMSTATETYPE TransformStateType, + D3DMATRIX *D3DMatrix) +{ + return IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve(IDirect3DDevice7 *iface, + D3DTRANSFORMSTATETYPE TransformStateType, + D3DMATRIX *D3DMatrix) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_MultiplyTransform(iface, TransformStateType, D3DMatrix); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_MultiplyTransform(IDirect3DDevice3 *iface, D3DTRANSFORMSTATETYPE TransformStateType, D3DMATRIX *D3DMatrix) @@ -3250,7 +3500,7 @@ Thunk_IDirect3DDeviceImpl_2_MultiplyTransform(IDirect3DDevice2 *iface, * For details, see IWineD3DDevice::DrawPrimitiveUP * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, @@ -3321,6 +3571,35 @@ IDirect3DDeviceImpl_7_DrawPrimitive(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + DWORD VertexType, + void *Vertices, + DWORD VertexCount, + DWORD Flags) +{ + return IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + DWORD VertexType, + void *Vertices, + DWORD VertexCount, + DWORD Flags) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_DrawPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Flags); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_DrawPrimitive(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, @@ -3392,7 +3671,7 @@ Thunk_IDirect3DDeviceImpl_2_DrawPrimitive(IDirect3DDevice2 *iface, * For details, see IWineD3DDevice::DrawIndexedPrimitiveUP * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, @@ -3463,6 +3742,39 @@ IDirect3DDeviceImpl_7_DrawIndexedPrimitive(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + DWORD VertexType, + void *Vertices, + DWORD VertexCount, + WORD *Indices, + DWORD IndexCount, + DWORD Flags) +{ + return IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + DWORD VertexType, + void *Vertices, + DWORD VertexCount, + WORD *Indices, + DWORD IndexCount, + DWORD Flags) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitive(iface, PrimitiveType, VertexType, Vertices, VertexCount, Indices, IndexCount, Flags); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, @@ -3633,7 +3945,7 @@ Thunk_IDirect3DDeviceImpl_2_GetClipStatus(IDirect3DDevice2 *iface, * (For details, see IWineD3DDevice::DrawPrimitiveStrided) * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, @@ -3746,6 +4058,35 @@ IDirect3DDeviceImpl_7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + DWORD VertexType, + D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, + DWORD VertexCount, + DWORD Flags) +{ + return IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + DWORD VertexType, + D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, + DWORD VertexCount, + DWORD Flags) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_DrawPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Flags); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, @@ -3780,7 +4121,7 @@ Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided(IDirect3DDevice3 *iface, * (For more details, see IWineD3DDevice::DrawIndexedPrimitiveStrided) * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType, DWORD VertexType, @@ -3898,18 +4239,51 @@ IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface, } static HRESULT WINAPI -Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface, - D3DPRIMITIVETYPE PrimitiveType, - DWORD VertexType, - D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, - DWORD VertexCount, - WORD *Indices, - DWORD IndexCount, - DWORD Flags) -{ - ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface); - TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags); - return IDirect3DDevice7_DrawIndexedPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7), +IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + DWORD VertexType, + D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, + DWORD VertexCount, + WORD *Indices, + DWORD IndexCount, + DWORD Flags) +{ + return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + DWORD VertexType, + D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, + DWORD VertexCount, + WORD *Indices, + DWORD IndexCount, + DWORD Flags) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided(iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI +Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface, + D3DPRIMITIVETYPE PrimitiveType, + DWORD VertexType, + D3DDRAWPRIMITIVESTRIDEDDATA *D3DDrawPrimStrideData, + DWORD VertexCount, + WORD *Indices, + DWORD IndexCount, + DWORD Flags) +{ + ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface); + TRACE_(ddraw_thunk)("(%p)->(%08x,%08x,%p,%08x,%p,%08x,%08x) thunking to IDirect3DDevice7 interface.\n", iface, PrimitiveType, VertexType, D3DDrawPrimStrideData, VertexCount, Indices, IndexCount, Flags); + return IDirect3DDevice7_DrawIndexedPrimitiveStrided(ICOM_INTERFACE(This, IDirect3DDevice7), PrimitiveType, VertexType, D3DDrawPrimStrideData, @@ -3938,7 +4312,7 @@ Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided(IDirect3DDevice3 *iface, * DDERR_INVALIDPARAMS if D3DVertexBuf is NULL * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf, @@ -4037,6 +4411,35 @@ IDirect3DDeviceImpl_7_DrawPrimitiveVB(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + IDirect3DVertexBuffer7 *D3DVertexBuf, + DWORD StartVertex, + DWORD NumVertices, + DWORD Flags) +{ + return IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + IDirect3DVertexBuffer7 *D3DVertexBuf, + DWORD StartVertex, + DWORD NumVertices, + DWORD Flags) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_DrawPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Flags); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, @@ -4073,7 +4476,7 @@ Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB(IDirect3DDevice3 *iface, * Return values * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer7 *D3DVertexBuf, @@ -4210,6 +4613,39 @@ IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + IDirect3DVertexBuffer7 *D3DVertexBuf, + DWORD StartVertex, + DWORD NumVertices, + WORD *Indices, + DWORD IndexCount, + DWORD Flags) +{ + return IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve(IDirect3DDevice7 *iface, + D3DPRIMITIVETYPE PrimitiveType, + IDirect3DVertexBuffer7 *D3DVertexBuf, + DWORD StartVertex, + DWORD NumVertices, + WORD *Indices, + DWORD IndexCount, + DWORD Flags) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB(iface, PrimitiveType, D3DVertexBuf, StartVertex, NumVertices, Indices, IndexCount, Flags); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface, D3DPRIMITIVETYPE PrimitiveType, IDirect3DVertexBuffer *D3DVertexBuf, @@ -4332,7 +4768,7 @@ Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility(IDirect3DDevice3 *iface, * For details, see IWineD3DDevice::GetTexture * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface, DWORD Stage, IDirectDrawSurface7 **Texture) @@ -4367,6 +4803,29 @@ IDirect3DDeviceImpl_7_GetTexture(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetTexture_FPUSetup(IDirect3DDevice7 *iface, + DWORD Stage, + IDirectDrawSurface7 **Texture) +{ + return IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetTexture_FPUPreserve(IDirect3DDevice7 *iface, + DWORD Stage, + IDirectDrawSurface7 **Texture) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_GetTexture(iface, Stage, Texture); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, DWORD Stage, IDirect3DTexture2 **Texture2) @@ -4403,7 +4862,7 @@ Thunk_IDirect3DDeviceImpl_3_GetTexture(IDirect3DDevice3 *iface, * For details, see IWineD3DDevice::SetTexture * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface, DWORD Stage, IDirectDrawSurface7 *Texture) @@ -4423,6 +4882,29 @@ IDirect3DDeviceImpl_7_SetTexture(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetTexture_FPUSetup(IDirect3DDevice7 *iface, + DWORD Stage, + IDirectDrawSurface7 *Texture) +{ + return IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetTexture_FPUPreserve(IDirect3DDevice7 *iface, + DWORD Stage, + IDirectDrawSurface7 *Texture) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_SetTexture(iface, Stage, Texture); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface, DWORD Stage, IDirect3DTexture2 *Texture2) @@ -4506,7 +4988,7 @@ IDirect3DDeviceImpl_3_SetTexture(IDirect3DDevice3 *iface, * For details, see IWineD3DDevice::GetTextureStageState * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, @@ -4598,6 +5080,31 @@ IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup(IDirect3DDevice7 *iface, + DWORD Stage, + D3DTEXTURESTAGESTATETYPE TexStageStateType, + DWORD *State) +{ + return IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface, + DWORD Stage, + D3DTEXTURESTAGESTATETYPE TexStageStateType, + DWORD *State) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_GetTextureStageState(iface, Stage, TexStageStateType, State); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, @@ -4629,7 +5136,7 @@ Thunk_IDirect3DDeviceImpl_3_GetTextureStageState(IDirect3DDevice3 *iface, * For details, see IWineD3DDevice::SetTextureStageState * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, @@ -4725,6 +5232,31 @@ IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup(IDirect3DDevice7 *iface, + DWORD Stage, + D3DTEXTURESTAGESTATETYPE TexStageStateType, + DWORD State) +{ + return IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve(IDirect3DDevice7 *iface, + DWORD Stage, + D3DTEXTURESTAGESTATETYPE TexStageStateType, + DWORD State) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_SetTextureStageState(iface, Stage, TexStageStateType, State); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE TexStageStateType, @@ -4756,7 +5288,7 @@ Thunk_IDirect3DDeviceImpl_3_SetTextureStageState(IDirect3DDevice3 *iface, * See IWineD3DDevice::ValidateDevice for more details * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface, DWORD *NumPasses) { @@ -4771,6 +5303,27 @@ IDirect3DDeviceImpl_7_ValidateDevice(IDirect3DDevice7 *iface, } static HRESULT WINAPI +IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup(IDirect3DDevice7 *iface, + DWORD *NumPasses) +{ + return IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve(IDirect3DDevice7 *iface, + DWORD *NumPasses) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_ValidateDevice(iface, NumPasses); + set_fpu_control_word(old_fpucw); + + return hr; +} + +static HRESULT WINAPI Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, DWORD *Passes) { @@ -4801,7 +5354,7 @@ Thunk_IDirect3DDeviceImpl_3_ValidateDevice(IDirect3DDevice3 *iface, * For details, see IWineD3DDevice::Clear * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, DWORD Count, D3DRECT *Rects, @@ -4821,6 +5374,37 @@ IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, return hr; } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_Clear_FPUSetup(IDirect3DDevice7 *iface, + DWORD Count, + D3DRECT *Rects, + DWORD Flags, + D3DCOLOR Color, + D3DVALUE Z, + DWORD Stencil) +{ + return IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_Clear_FPUPreserve(IDirect3DDevice7 *iface, + DWORD Count, + D3DRECT *Rects, + DWORD Flags, + D3DCOLOR Color, + D3DVALUE Z, + DWORD Stencil) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_Clear(iface, Count, Rects, Flags, Color, Z, Stencil); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::SetViewport * @@ -4838,7 +5422,7 @@ IDirect3DDeviceImpl_7_Clear(IDirect3DDevice7 *iface, * For more details, see IWineDDDevice::SetViewport * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *Data) { @@ -4857,6 +5441,27 @@ IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface, return hr; } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetViewport_FPUSetup(IDirect3DDevice7 *iface, + D3DVIEWPORT7 *Data) +{ + return IDirect3DDeviceImpl_7_SetViewport(iface, Data); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetViewport_FPUPreserve(IDirect3DDevice7 *iface, + D3DVIEWPORT7 *Data) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_SetViewport(iface, Data); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice::GetViewport * @@ -4873,7 +5478,7 @@ IDirect3DDeviceImpl_7_SetViewport(IDirect3DDevice7 *iface, * For more details, see IWineD3DDevice::GetViewport * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *Data) { @@ -4893,6 +5498,27 @@ IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface, return hr_ddraw_from_wined3d(hr); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetViewport_FPUSetup(IDirect3DDevice7 *iface, + D3DVIEWPORT7 *Data) +{ + return IDirect3DDeviceImpl_7_GetViewport(iface, Data); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetViewport_FPUPreserve(IDirect3DDevice7 *iface, + D3DVIEWPORT7 *Data) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_GetViewport(iface, Data); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::SetMaterial * @@ -4909,7 +5535,7 @@ IDirect3DDeviceImpl_7_GetViewport(IDirect3DDevice7 *iface, * For more details, see IWineD3DDevice::SetMaterial * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *Mat) { @@ -4925,6 +5551,27 @@ IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface, return hr_ddraw_from_wined3d(hr); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetMaterial_FPUSetup(IDirect3DDevice7 *iface, + D3DMATERIAL7 *Mat) +{ + return IDirect3DDeviceImpl_7_SetMaterial(iface, Mat); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve(IDirect3DDevice7 *iface, + D3DMATERIAL7 *Mat) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_SetMaterial(iface, Mat); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::GetMaterial * @@ -4941,7 +5588,7 @@ IDirect3DDeviceImpl_7_SetMaterial(IDirect3DDevice7 *iface, * For more details, see IWineD3DDevice::GetMaterial * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface, D3DMATERIAL7 *Mat) { @@ -4957,6 +5604,27 @@ IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface, return hr_ddraw_from_wined3d(hr); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetMaterial_FPUSetup(IDirect3DDevice7 *iface, + D3DMATERIAL7 *Mat) +{ + return IDirect3DDeviceImpl_7_GetMaterial(iface, Mat); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve(IDirect3DDevice7 *iface, + D3DMATERIAL7 *Mat) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_GetMaterial(iface, Mat); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::SetLight * @@ -4973,7 +5641,7 @@ IDirect3DDeviceImpl_7_GetMaterial(IDirect3DDevice7 *iface, * For more details, see IWineD3DDevice::SetLight * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface, DWORD LightIndex, D3DLIGHT7 *Light) @@ -4991,6 +5659,29 @@ IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface, return hr_ddraw_from_wined3d(hr); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetLight_FPUSetup(IDirect3DDevice7 *iface, + DWORD LightIndex, + D3DLIGHT7 *Light) +{ + return IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetLight_FPUPreserve(IDirect3DDevice7 *iface, + DWORD LightIndex, + D3DLIGHT7 *Light) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_SetLight(iface, LightIndex, Light); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::GetLight * @@ -5005,7 +5696,7 @@ IDirect3DDeviceImpl_7_SetLight(IDirect3DDevice7 *iface, * For details, see IWineD3DDevice::GetLight * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface, DWORD LightIndex, D3DLIGHT7 *Light) @@ -5025,6 +5716,29 @@ IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface, return hr_ddraw_from_wined3d(rc); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetLight_FPUSetup(IDirect3DDevice7 *iface, + DWORD LightIndex, + D3DLIGHT7 *Light) +{ + return IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetLight_FPUPreserve(IDirect3DDevice7 *iface, + DWORD LightIndex, + D3DLIGHT7 *Light) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_GetLight(iface, LightIndex, Light); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::BeginStateBlock * @@ -5037,7 +5751,7 @@ IDirect3DDeviceImpl_7_GetLight(IDirect3DDevice7 *iface, * For details see IWineD3DDevice::BeginStateBlock * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); @@ -5050,6 +5764,25 @@ IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface) return hr_ddraw_from_wined3d(hr); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup(IDirect3DDevice7 *iface) +{ + return IDirect3DDeviceImpl_7_BeginStateBlock(iface); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve(IDirect3DDevice7 *iface) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_BeginStateBlock(iface); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::EndStateBlock * @@ -5067,7 +5800,7 @@ IDirect3DDeviceImpl_7_BeginStateBlock(IDirect3DDevice7 *iface) * See IWineD3DDevice::EndStateBlock for more details * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface, DWORD *BlockHandle) { @@ -5096,6 +5829,27 @@ IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface, return hr_ddraw_from_wined3d(hr); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup(IDirect3DDevice7 *iface, + DWORD *BlockHandle) +{ + return IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve(IDirect3DDevice7 *iface, + DWORD *BlockHandle) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_EndStateBlock(iface, BlockHandle); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::PreLoad * @@ -5113,7 +5867,7 @@ IDirect3DDeviceImpl_7_EndStateBlock(IDirect3DDevice7 *iface, * See IWineD3DSurface::PreLoad for details * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface, IDirectDrawSurface7 *Texture) { @@ -5131,6 +5885,27 @@ IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface, return D3D_OK; } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_PreLoad_FPUSetup(IDirect3DDevice7 *iface, + IDirectDrawSurface7 *Texture) +{ + return IDirect3DDeviceImpl_7_PreLoad(iface, Texture); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_PreLoad_FPUPreserve(IDirect3DDevice7 *iface, + IDirectDrawSurface7 *Texture) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_PreLoad(iface, Texture); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::ApplyStateBlock * @@ -5144,7 +5919,7 @@ IDirect3DDeviceImpl_7_PreLoad(IDirect3DDevice7 *iface, * D3DERR_INVALIDSTATEBLOCK if BlockHandle is NULL * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface, DWORD BlockHandle) { @@ -5171,6 +5946,27 @@ IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface, return hr_ddraw_from_wined3d(hr); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup(IDirect3DDevice7 *iface, + DWORD BlockHandle) +{ + return IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve(IDirect3DDevice7 *iface, + DWORD BlockHandle) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_ApplyStateBlock(iface, BlockHandle); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::CaptureStateBlock * @@ -5187,7 +5983,7 @@ IDirect3DDeviceImpl_7_ApplyStateBlock(IDirect3DDevice7 *iface, * See IWineD3DDevice::CaptureStateBlock for more details * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface, DWORD BlockHandle) { @@ -5214,6 +6010,27 @@ IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface, return hr_ddraw_from_wined3d(hr); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup(IDirect3DDevice7 *iface, + DWORD BlockHandle) +{ + return IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve(IDirect3DDevice7 *iface, + DWORD BlockHandle) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_CaptureStateBlock(iface, BlockHandle); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::DeleteStateBlock * @@ -5229,7 +6046,7 @@ IDirect3DDeviceImpl_7_CaptureStateBlock(IDirect3DDevice7 *iface, * D3DERR_INVALIDSTATEBLOCK if BlockHandle is 0 * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface, DWORD BlockHandle) { @@ -5263,6 +6080,27 @@ IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface, return D3D_OK; } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup(IDirect3DDevice7 *iface, + DWORD BlockHandle) +{ + return IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve(IDirect3DDevice7 *iface, + DWORD BlockHandle) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_DeleteStateBlock(iface, BlockHandle); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::CreateStateBlock * @@ -5279,7 +6117,7 @@ IDirect3DDeviceImpl_7_DeleteStateBlock(IDirect3DDevice7 *iface, * DDERR_INVALIDPARAMS if BlockHandle is NULL * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface, D3DSTATEBLOCKTYPE Type, DWORD *BlockHandle) @@ -5318,6 +6156,29 @@ IDirect3DDeviceImpl_7_CreateStateBlock(IDirect3DDevice7 *iface, return hr_ddraw_from_wined3d(hr); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup(IDirect3DDevice7 *iface, + D3DSTATEBLOCKTYPE Type, + DWORD *BlockHandle) +{ + return IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve(IDirect3DDevice7 *iface, + D3DSTATEBLOCKTYPE Type, + DWORD *BlockHandle) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr =IDirect3DDeviceImpl_7_CreateStateBlock(iface, Type, BlockHandle); + set_fpu_control_word(old_fpucw); + + return hr; +} + /* Helper function for IDirect3DDeviceImpl_7_Load. */ static BOOL is_mip_level_subset(IDirectDrawSurfaceImpl *dest, IDirectDrawSurfaceImpl *src) @@ -5487,7 +6348,7 @@ static void copy_mipmap_chain(IDirect3DDeviceImpl *device, * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface, IDirectDrawSurface7 *DestTex, POINT *DestPoint, @@ -5658,6 +6519,35 @@ IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface, return D3D_OK; } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_Load_FPUSetup(IDirect3DDevice7 *iface, + IDirectDrawSurface7 *DestTex, + POINT *DestPoint, + IDirectDrawSurface7 *SrcTex, + RECT *SrcRect, + DWORD Flags) +{ + return IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_Load_FPUPreserve(IDirect3DDevice7 *iface, + IDirectDrawSurface7 *DestTex, + POINT *DestPoint, + IDirectDrawSurface7 *SrcTex, + RECT *SrcRect, + DWORD Flags) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_Load(iface, DestTex, DestPoint, SrcTex, SrcRect, Flags); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::LightEnable * @@ -5674,7 +6564,7 @@ IDirect3DDeviceImpl_7_Load(IDirect3DDevice7 *iface, * For more details, see IWineD3DDevice::SetLightEnable * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface, DWORD LightIndex, BOOL Enable) @@ -5689,6 +6579,29 @@ IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface, return hr_ddraw_from_wined3d(hr); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_LightEnable_FPUSetup(IDirect3DDevice7 *iface, + DWORD LightIndex, + BOOL Enable) +{ + return IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_LightEnable_FPUPreserve(IDirect3DDevice7 *iface, + DWORD LightIndex, + BOOL Enable) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_LightEnable(iface, LightIndex, Enable); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::GetLightEnable * @@ -5706,7 +6619,7 @@ IDirect3DDeviceImpl_7_LightEnable(IDirect3DDevice7 *iface, * See IWineD3DDevice::GetLightEnable for more details * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface, DWORD LightIndex, BOOL* Enable) @@ -5724,6 +6637,29 @@ IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface, return hr_ddraw_from_wined3d(hr); } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup(IDirect3DDevice7 *iface, + DWORD LightIndex, + BOOL* Enable) +{ + return IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve(IDirect3DDevice7 *iface, + DWORD LightIndex, + BOOL* Enable) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_GetLightEnable(iface, LightIndex, Enable); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::SetClipPlane * @@ -5741,7 +6677,7 @@ IDirect3DDeviceImpl_7_GetLightEnable(IDirect3DDevice7 *iface, * See IWineD3DDevice::SetClipPlane for more details * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface, DWORD Index, D3DVALUE* PlaneEquation) @@ -5759,6 +6695,29 @@ IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface, return hr; } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup(IDirect3DDevice7 *iface, + DWORD Index, + D3DVALUE* PlaneEquation) +{ + return IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, + DWORD Index, + D3DVALUE* PlaneEquation) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_SetClipPlane(iface, Index, PlaneEquation); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::GetClipPlane * @@ -5774,7 +6733,7 @@ IDirect3DDeviceImpl_7_SetClipPlane(IDirect3DDevice7 *iface, * See IWineD3DDevice::GetClipPlane for more details * *****************************************************************************/ -static HRESULT WINAPI +static HRESULT IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface, DWORD Index, D3DVALUE* PlaneEquation) @@ -5792,6 +6751,29 @@ IDirect3DDeviceImpl_7_GetClipPlane(IDirect3DDevice7 *iface, return hr; } +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup(IDirect3DDevice7 *iface, + DWORD Index, + D3DVALUE* PlaneEquation) +{ + return IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation); +} + +static HRESULT WINAPI +IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve(IDirect3DDevice7 *iface, + DWORD Index, + D3DVALUE* PlaneEquation) +{ + HRESULT hr; + WORD old_fpucw; + + old_fpucw = d3d_fpu_setup(); + hr = IDirect3DDeviceImpl_7_GetClipPlane(iface, Index, PlaneEquation); + set_fpu_control_word(old_fpucw); + + return hr; +} + /***************************************************************************** * IDirect3DDevice7::GetInfo * @@ -5832,58 +6814,123 @@ IDirect3DDeviceImpl_7_GetInfo(IDirect3DDevice7 *iface, return S_FALSE; /* According to MSDN, this is valid for a non-debug driver */ } -const IDirect3DDevice7Vtbl IDirect3DDevice7_Vtbl = +/* For performance optimization, devices created in FPUSETUP and FPUPRESERVE modes + * have separate vtables. Simple functions where this doesn't matter like GetDirect3D + * are not duplicated. + + * Device created with DDSCL_FPUSETUP (d3d7 default) - device methods assume that FPU + * has already been setup for optimal d3d operation. + + * Device created with DDSCL_FPUPRESERVE - resets and restores FPU mode when necessary in + * d3d calls (FPU may be in a mode non-suitable for d3d when the app calls d3d). Required + * by Sacrifice (game). */ +const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUSetup_Vtbl = +{ + /*** IUnknown Methods ***/ + IDirect3DDeviceImpl_7_QueryInterface, + IDirect3DDeviceImpl_7_AddRef, + IDirect3DDeviceImpl_7_Release, + /*** IDirect3DDevice7 ***/ + IDirect3DDeviceImpl_7_GetCaps_FPUSetup, + IDirect3DDeviceImpl_7_EnumTextureFormats_FPUSetup, + IDirect3DDeviceImpl_7_BeginScene_FPUSetup, + IDirect3DDeviceImpl_7_EndScene_FPUSetup, + IDirect3DDeviceImpl_7_GetDirect3D, + IDirect3DDeviceImpl_7_SetRenderTarget_FPUSetup, + IDirect3DDeviceImpl_7_GetRenderTarget, + IDirect3DDeviceImpl_7_Clear_FPUSetup, + IDirect3DDeviceImpl_7_SetTransform_FPUSetup, + IDirect3DDeviceImpl_7_GetTransform_FPUSetup, + IDirect3DDeviceImpl_7_SetViewport_FPUSetup, + IDirect3DDeviceImpl_7_MultiplyTransform_FPUSetup, + IDirect3DDeviceImpl_7_GetViewport_FPUSetup, + IDirect3DDeviceImpl_7_SetMaterial_FPUSetup, + IDirect3DDeviceImpl_7_GetMaterial_FPUSetup, + IDirect3DDeviceImpl_7_SetLight_FPUSetup, + IDirect3DDeviceImpl_7_GetLight_FPUSetup, + IDirect3DDeviceImpl_7_SetRenderState_FPUSetup, + IDirect3DDeviceImpl_7_GetRenderState_FPUSetup, + IDirect3DDeviceImpl_7_BeginStateBlock_FPUSetup, + IDirect3DDeviceImpl_7_EndStateBlock_FPUSetup, + IDirect3DDeviceImpl_7_PreLoad_FPUSetup, + IDirect3DDeviceImpl_7_DrawPrimitive_FPUSetup, + IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUSetup, + IDirect3DDeviceImpl_7_SetClipStatus, + IDirect3DDeviceImpl_7_GetClipStatus, + IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUSetup, + IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUSetup, + IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUSetup, + IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUSetup, + IDirect3DDeviceImpl_7_ComputeSphereVisibility, + IDirect3DDeviceImpl_7_GetTexture_FPUSetup, + IDirect3DDeviceImpl_7_SetTexture_FPUSetup, + IDirect3DDeviceImpl_7_GetTextureStageState_FPUSetup, + IDirect3DDeviceImpl_7_SetTextureStageState_FPUSetup, + IDirect3DDeviceImpl_7_ValidateDevice_FPUSetup, + IDirect3DDeviceImpl_7_ApplyStateBlock_FPUSetup, + IDirect3DDeviceImpl_7_CaptureStateBlock_FPUSetup, + IDirect3DDeviceImpl_7_DeleteStateBlock_FPUSetup, + IDirect3DDeviceImpl_7_CreateStateBlock_FPUSetup, + IDirect3DDeviceImpl_7_Load_FPUSetup, + IDirect3DDeviceImpl_7_LightEnable_FPUSetup, + IDirect3DDeviceImpl_7_GetLightEnable_FPUSetup, + IDirect3DDeviceImpl_7_SetClipPlane_FPUSetup, + IDirect3DDeviceImpl_7_GetClipPlane_FPUSetup, + IDirect3DDeviceImpl_7_GetInfo +}; + +const IDirect3DDevice7Vtbl IDirect3DDevice7_FPUPreserve_Vtbl = { /*** IUnknown Methods ***/ IDirect3DDeviceImpl_7_QueryInterface, IDirect3DDeviceImpl_7_AddRef, IDirect3DDeviceImpl_7_Release, /*** IDirect3DDevice7 ***/ - IDirect3DDeviceImpl_7_GetCaps, - IDirect3DDeviceImpl_7_EnumTextureFormats, - IDirect3DDeviceImpl_7_BeginScene, - IDirect3DDeviceImpl_7_EndScene, + IDirect3DDeviceImpl_7_GetCaps_FPUPreserve, + IDirect3DDeviceImpl_7_EnumTextureFormats_FPUPreserve, + IDirect3DDeviceImpl_7_BeginScene_FPUPreserve, + IDirect3DDeviceImpl_7_EndScene_FPUPreserve, IDirect3DDeviceImpl_7_GetDirect3D, - IDirect3DDeviceImpl_7_SetRenderTarget, + IDirect3DDeviceImpl_7_SetRenderTarget_FPUPreserve, IDirect3DDeviceImpl_7_GetRenderTarget, - IDirect3DDeviceImpl_7_Clear, - IDirect3DDeviceImpl_7_SetTransform, - IDirect3DDeviceImpl_7_GetTransform, - IDirect3DDeviceImpl_7_SetViewport, - IDirect3DDeviceImpl_7_MultiplyTransform, - IDirect3DDeviceImpl_7_GetViewport, - IDirect3DDeviceImpl_7_SetMaterial, - IDirect3DDeviceImpl_7_GetMaterial, - IDirect3DDeviceImpl_7_SetLight, - IDirect3DDeviceImpl_7_GetLight, - IDirect3DDeviceImpl_7_SetRenderState, - IDirect3DDeviceImpl_7_GetRenderState, - IDirect3DDeviceImpl_7_BeginStateBlock, - IDirect3DDeviceImpl_7_EndStateBlock, - IDirect3DDeviceImpl_7_PreLoad, - IDirect3DDeviceImpl_7_DrawPrimitive, - IDirect3DDeviceImpl_7_DrawIndexedPrimitive, + IDirect3DDeviceImpl_7_Clear_FPUPreserve, + IDirect3DDeviceImpl_7_SetTransform_FPUPreserve, + IDirect3DDeviceImpl_7_GetTransform_FPUPreserve, + IDirect3DDeviceImpl_7_SetViewport_FPUPreserve, + IDirect3DDeviceImpl_7_MultiplyTransform_FPUPreserve, + IDirect3DDeviceImpl_7_GetViewport_FPUPreserve, + IDirect3DDeviceImpl_7_SetMaterial_FPUPreserve, + IDirect3DDeviceImpl_7_GetMaterial_FPUPreserve, + IDirect3DDeviceImpl_7_SetLight_FPUPreserve, + IDirect3DDeviceImpl_7_GetLight_FPUPreserve, + IDirect3DDeviceImpl_7_SetRenderState_FPUPreserve, + IDirect3DDeviceImpl_7_GetRenderState_FPUPreserve, + IDirect3DDeviceImpl_7_BeginStateBlock_FPUPreserve, + IDirect3DDeviceImpl_7_EndStateBlock_FPUPreserve, + IDirect3DDeviceImpl_7_PreLoad_FPUPreserve, + IDirect3DDeviceImpl_7_DrawPrimitive_FPUPreserve, + IDirect3DDeviceImpl_7_DrawIndexedPrimitive_FPUPreserve, IDirect3DDeviceImpl_7_SetClipStatus, IDirect3DDeviceImpl_7_GetClipStatus, - IDirect3DDeviceImpl_7_DrawPrimitiveStrided, - IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided, - IDirect3DDeviceImpl_7_DrawPrimitiveVB, - IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB, + IDirect3DDeviceImpl_7_DrawPrimitiveStrided_FPUPreserve, + IDirect3DDeviceImpl_7_DrawIndexedPrimitiveStrided_FPUPreserve, + IDirect3DDeviceImpl_7_DrawPrimitiveVB_FPUPreserve, + IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB_FPUPreserve, IDirect3DDeviceImpl_7_ComputeSphereVisibility, - IDirect3DDeviceImpl_7_GetTexture, - IDirect3DDeviceImpl_7_SetTexture, - IDirect3DDeviceImpl_7_GetTextureStageState, - IDirect3DDeviceImpl_7_SetTextureStageState, - IDirect3DDeviceImpl_7_ValidateDevice, - IDirect3DDeviceImpl_7_ApplyStateBlock, - IDirect3DDeviceImpl_7_CaptureStateBlock, - IDirect3DDeviceImpl_7_DeleteStateBlock, - IDirect3DDeviceImpl_7_CreateStateBlock, - IDirect3DDeviceImpl_7_Load, - IDirect3DDeviceImpl_7_LightEnable, - IDirect3DDeviceImpl_7_GetLightEnable, - IDirect3DDeviceImpl_7_SetClipPlane, - IDirect3DDeviceImpl_7_GetClipPlane, + IDirect3DDeviceImpl_7_GetTexture_FPUPreserve, + IDirect3DDeviceImpl_7_SetTexture_FPUPreserve, + IDirect3DDeviceImpl_7_GetTextureStageState_FPUPreserve, + IDirect3DDeviceImpl_7_SetTextureStageState_FPUPreserve, + IDirect3DDeviceImpl_7_ValidateDevice_FPUPreserve, + IDirect3DDeviceImpl_7_ApplyStateBlock_FPUPreserve, + IDirect3DDeviceImpl_7_CaptureStateBlock_FPUPreserve, + IDirect3DDeviceImpl_7_DeleteStateBlock_FPUPreserve, + IDirect3DDeviceImpl_7_CreateStateBlock_FPUPreserve, + IDirect3DDeviceImpl_7_Load_FPUPreserve, + IDirect3DDeviceImpl_7_LightEnable_FPUPreserve, + IDirect3DDeviceImpl_7_GetLightEnable_FPUPreserve, + IDirect3DDeviceImpl_7_SetClipPlane_FPUPreserve, + IDirect3DDeviceImpl_7_GetClipPlane_FPUPreserve, IDirect3DDeviceImpl_7_GetInfo }; diff --git a/dlls/ddraw/direct3d.c b/dlls/ddraw/direct3d.c index ff24762509d..6c47e695a67 100644 --- a/dlls/ddraw/direct3d.c +++ b/dlls/ddraw/direct3d.c @@ -805,7 +805,11 @@ IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface, return DDERR_OUTOFMEMORY; } - ICOM_INIT_INTERFACE(object, IDirect3DDevice7, IDirect3DDevice7_Vtbl); + if (This->cooperative_level & DDSCL_FPUPRESERVE) + ICOM_INIT_INTERFACE(object, IDirect3DDevice7, IDirect3DDevice7_FPUPreserve_Vtbl); + else + ICOM_INIT_INTERFACE(object, IDirect3DDevice7, IDirect3DDevice7_FPUSetup_Vtbl); + ICOM_INIT_INTERFACE(object, IDirect3DDevice3, IDirect3DDevice3_Vtbl); ICOM_INIT_INTERFACE(object, IDirect3DDevice2, IDirect3DDevice2_Vtbl); ICOM_INIT_INTERFACE(object, IDirect3DDevice, IDirect3DDevice1_Vtbl); diff --git a/dlls/ddraw/main.c b/dlls/ddraw/main.c index ac1378d2a3d..d03a89c1d2f 100644 --- a/dlls/ddraw/main.c +++ b/dlls/ddraw/main.c @@ -49,7 +49,6 @@ typedef IWineD3D* (WINAPI *fnWineDirect3DCreate)(UINT, UINT, IUnknown *); -static HMODULE hWineD3D = (HMODULE) -1; static fnWineDirect3DCreate pWineDirect3DCreate; WINE_DEFAULT_DEBUG_CHANNEL(ddraw); @@ -72,6 +71,31 @@ CRITICAL_SECTION ddraw_cs = { &ddraw_cs_debug, -1, 0, 0, 0, 0 }; /* value of ForceRefreshRate */ DWORD force_refresh_rate = 0; +/* + * Helper Function for DDRAW_Create and DirectDrawCreateClipper for + * lazy loading of the Wine D3D driver. + * + * Returns + * TRUE on success + * FALSE on failure. + */ + +BOOL LoadWineD3D(void) +{ + static HMODULE hWineD3D = (HMODULE) -1; + if (hWineD3D == (HMODULE) -1) + { + hWineD3D = LoadLibraryA("wined3d"); + if (hWineD3D) + { + pWineDirect3DCreate = (fnWineDirect3DCreate) GetProcAddress(hWineD3D, "WineDirect3DCreate"); + pWineDirect3DCreateClipper = (fnWineDirect3DCreateClipper) GetProcAddress(hWineD3D, "WineDirect3DCreateClipper"); + return TRUE; + } + } + return hWineD3D != NULL; +} + /*********************************************************************** * * Helper function for DirectDrawCreate and friends @@ -171,17 +195,7 @@ DDRAW_Create(const GUID *guid, This->orig_width = GetSystemMetrics(SM_CXSCREEN); This->orig_height = GetSystemMetrics(SM_CYSCREEN); - if (hWineD3D == (HMODULE) -1) - { - hWineD3D = LoadLibraryA("wined3d"); - if (hWineD3D) - { - pWineDirect3DCreate = (fnWineDirect3DCreate) GetProcAddress(hWineD3D, "WineDirect3DCreate"); - pWineDirect3DCreateClipper = (fnWineDirect3DCreateClipper) GetProcAddress(hWineD3D, "WineDirect3DCreateClipper"); - } - } - - if (!hWineD3D) + if (!LoadWineD3D()) { ERR("Couldn't load WineD3D - OpenGL libs not present?\n"); hr = DDERR_NODIRECTDRAWSUPPORT; diff --git a/dlls/devenum/mediacatenum.c b/dlls/devenum/mediacatenum.c index 331130bad76..a4d45dce29d 100644 --- a/dlls/devenum/mediacatenum.c +++ b/dlls/devenum/mediacatenum.c @@ -173,10 +173,13 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read( switch (V_VT(pVar)) { case VT_EMPTY: + V_VT(pVar) = VT_ARRAY | VT_UI1; + /* fall through */ case VT_ARRAY | VT_UI1: if (!(V_UNION(pVar, parray) = SafeArrayCreate(VT_UI1, 1, &bound))) res = E_OUTOFMEMORY; - res = S_OK; + else + res = S_OK; break; } diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c index cd0861a6ce2..87e9bbab81b 100644 --- a/dlls/dsound/dsound.c +++ b/dlls/dsound/dsound.c @@ -1282,7 +1282,8 @@ ULONG DirectSoundDevice_Release(DirectSoundDevice * device) HeapFree(GetProcessHeap(), 0, device->tmp_buffer); HeapFree(GetProcessHeap(), 0, device->mix_buffer); - HeapFree(GetProcessHeap(), 0, device->buffer); + if (device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) + HeapFree(GetProcessHeap(), 0, device->buffer); RtlDeleteResource(&device->buffer_list_lock); device->mixlock.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&device->mixlock); diff --git a/dlls/dsound/tests/dsound.c b/dlls/dsound/tests/dsound.c index 6c816403705..4b84eb9008d 100644 --- a/dlls/dsound/tests/dsound.c +++ b/dlls/dsound/tests/dsound.c @@ -401,22 +401,42 @@ static HRESULT test_primary(LPGUID lpGuid) "IDirectSound_CreateSoundBuffer() should have failed: %s\n", DXGetErrorString8(rc)); + /* DSOUND: Error: NULL pointer is invalid */ /* DSOUND: Error: Invalid buffer description pointer */ rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL); ok(rc==DSERR_INVALIDPARAM && primary==0, "IDirectSound_CreateSoundBuffer() should have failed: rc=%s," "dsbo=%p\n",DXGetErrorString8(rc),primary); - /* DSOUND: Error: Invalid buffer description pointer */ - rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL); + /* DSOUND: Error: Invalid size */ + /* DSOUND: Error: Invalid buffer description */ + primary=NULL; + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc)-1; + rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); ok(rc==DSERR_INVALIDPARAM && primary==0, "IDirectSound_CreateSoundBuffer() should have failed: rc=%s," - "dsbo=0x%p\n",DXGetErrorString8(rc),primary); + "primary=%p\n",DXGetErrorString8(rc),primary); + /* DSOUND: Error: DSBCAPS_PRIMARYBUFFER flag with non-NULL lpwfxFormat */ + /* DSOUND: Error: Invalid buffer description pointer */ + primary=NULL; ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER; + bufdesc.lpwfxFormat=&wfx; + rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); + ok(rc==DSERR_INVALIDPARAM && primary==0, + "IDirectSound_CreateSoundBuffer() should have failed: rc=%s," + "primary=%p\n",DXGetErrorString8(rc),primary); - /* DSOUND: Error: Invalid size */ - /* DSOUND: Error: Invalid buffer description */ + /* DSOUND: Error: No DSBCAPS_PRIMARYBUFFER flag with NULL lpwfxFormat */ + /* DSOUND: Error: Invalid buffer description pointer */ + primary=NULL; + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=0; + bufdesc.lpwfxFormat=NULL; rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); ok(rc==DSERR_INVALIDPARAM && primary==0, "IDirectSound_CreateSoundBuffer() should have failed: rc=%s," diff --git a/dlls/dxdiagn/provider.c b/dlls/dxdiagn/provider.c index 7fc7aa5cdff..44b30d89e6a 100644 --- a/dlls/dxdiagn/provider.c +++ b/dlls/dxdiagn/provider.c @@ -156,15 +156,20 @@ static inline HRESULT add_prop_str( IDxDiagContainer* cont, LPCWSTR prop, LPCWST static inline HRESULT add_prop_ui4( IDxDiagContainer* cont, LPCWSTR prop, DWORD data ) { - HRESULT hr; VARIANT var; V_VT( &var ) = VT_UI4; V_UI4( &var ) = data; - hr = IDxDiagContainerImpl_AddProp( cont, prop, &var ); - VariantClear( &var ); + return IDxDiagContainerImpl_AddProp( cont, prop, &var ); +} - return hr; +static inline HRESULT add_prop_bool( IDxDiagContainer* cont, LPCWSTR prop, BOOL data ) +{ + VARIANT var; + + V_VT( &var ) = VT_BOOL; + V_BOOL( &var ) = data; + return IDxDiagContainerImpl_AddProp( cont, prop, &var ); } /** @@ -189,7 +194,6 @@ static HRESULT DXDiag_AddFileDescContainer(IDxDiagContainer* pSubCont, const WCH static const WCHAR szFinal_Retail_v[] = {'F','i','n','a','l',' ','R','e','t','a','i','l',0}; static const WCHAR szEnglish_v[] = {'E','n','g','l','i','s','h',0}; static const WCHAR szVersionFormat[] = {'%','u','.','%','0','2','u','.','%','0','4','u','.','%','0','4','u',0}; - VARIANT v; WCHAR szFile[512]; WCHAR szVersion_v[1024]; @@ -210,15 +214,9 @@ static HRESULT DXDiag_AddFileDescContainer(IDxDiagContainer* pSubCont, const WCH boolret = GetFileVersionInfoW(szFile, 0, retval, pVersionInfo); boolret = VerQueryValueW(pVersionInfo, szSlashSep, (LPVOID) &pFileInfo, &uiLength); - V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(szFile); - hr = IDxDiagContainerImpl_AddProp(pSubCont, szPath, &v); - VariantClear(&v); - V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(szFileName); - hr = IDxDiagContainerImpl_AddProp(pSubCont, szName, &v); - VariantClear(&v); - V_VT(&v) = VT_BOOL; V_BOOL(&v) = boolret; - hr = IDxDiagContainerImpl_AddProp(pSubCont, bExists, &v); - VariantClear(&v); + add_prop_str(pSubCont, szPath, szFile); + add_prop_str(pSubCont, szName, szFileName); + add_prop_bool(pSubCont, bExists, boolret); if (boolret) { snprintfW(szVersion_v, sizeof(szVersion_v)/sizeof(szVersion_v[0]), @@ -230,27 +228,13 @@ static HRESULT DXDiag_AddFileDescContainer(IDxDiagContainer* pSubCont, const WCH TRACE("Found version as (%s)\n", debugstr_w(szVersion_v)); - V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(szVersion_v); - hr = IDxDiagContainerImpl_AddProp(pSubCont, szVersion, &v); - VariantClear(&v); - V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(szFinal_Retail_v); - hr = IDxDiagContainerImpl_AddProp(pSubCont, szAttributes, &v); - VariantClear(&v); - V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(szEnglish_v); - hr = IDxDiagContainerImpl_AddProp(pSubCont, szLanguageEnglish, &v); - VariantClear(&v); - V_VT(&v) = VT_UI4; V_UI4(&v) = pFileInfo->dwFileDateMS; - hr = IDxDiagContainerImpl_AddProp(pSubCont, dwFileTimeHigh, &v); - VariantClear(&v); - V_VT(&v) = VT_UI4; V_UI4(&v) = pFileInfo->dwFileDateLS; - hr = IDxDiagContainerImpl_AddProp(pSubCont, dwFileTimeLow, &v); - VariantClear(&v); - V_VT(&v) = VT_BOOL; V_BOOL(&v) = (0 != ((pFileInfo->dwFileFlags & pFileInfo->dwFileFlagsMask) & VS_FF_PRERELEASE)); - hr = IDxDiagContainerImpl_AddProp(pSubCont, bBeta, &v); - VariantClear(&v); - V_VT(&v) = VT_BOOL; V_BOOL(&v) = (0 != ((pFileInfo->dwFileFlags & pFileInfo->dwFileFlagsMask) & VS_FF_DEBUG)); - hr = IDxDiagContainerImpl_AddProp(pSubCont, bDebug, &v); - VariantClear(&v); + add_prop_str(pSubCont, szVersion, szVersion_v); + add_prop_str(pSubCont, szAttributes, szFinal_Retail_v); + add_prop_str(pSubCont, szLanguageEnglish, szEnglish_v); + add_prop_ui4(pSubCont, dwFileTimeHigh, pFileInfo->dwFileDateMS); + add_prop_ui4(pSubCont, dwFileTimeLow, pFileInfo->dwFileDateLS); + add_prop_bool(pSubCont, bBeta, 0 != ((pFileInfo->dwFileFlags & pFileInfo->dwFileFlagsMask) & VS_FF_PRERELEASE)); + add_prop_bool(pSubCont, bDebug, 0 != ((pFileInfo->dwFileFlags & pFileInfo->dwFileFlagsMask) & VS_FF_DEBUG)); } HeapFree(GetProcessHeap(), 0, pVersionInfo); @@ -280,42 +264,27 @@ static HRESULT DXDiag_InitDXDiagSystemInfoContainer(IDxDiagContainer* pSubCont) OSVERSIONINFOW info; VARIANT v; - V_VT(&v) = VT_UI4; V_UI4(&v) = 9; - IDxDiagContainerImpl_AddProp(pSubCont, dwDirectXVersionMajor, &v); - V_VT(&v) = VT_UI4; V_UI4(&v) = 0; - IDxDiagContainerImpl_AddProp(pSubCont, dwDirectXVersionMinor, &v); - V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(szDirectXVersionLetter_v); - IDxDiagContainerImpl_AddProp(pSubCont, szDirectXVersionLetter, &v); - VariantClear(&v); - V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(szDirectXVersionEnglish_v); - IDxDiagContainerImpl_AddProp(pSubCont, szDirectXVersionEnglish, &v); - VariantClear(&v); - V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(szDirectXVersionLongEnglish_v); - IDxDiagContainerImpl_AddProp(pSubCont, szDirectXVersionLongEnglish, &v); - VariantClear(&v); - V_VT(&v) = VT_BOOL; V_BOOL(&v) = FALSE; - IDxDiagContainerImpl_AddProp(pSubCont, bDebug, &v); + add_prop_ui4(pSubCont, dwDirectXVersionMajor, 9); + add_prop_ui4(pSubCont, dwDirectXVersionMinor, 0); + add_prop_str(pSubCont, szDirectXVersionLetter, szDirectXVersionLetter_v); + add_prop_str(pSubCont, szDirectXVersionEnglish, szDirectXVersionEnglish_v); + add_prop_str(pSubCont, szDirectXVersionLongEnglish, szDirectXVersionLongEnglish_v); + add_prop_bool(pSubCont, bDebug, FALSE); msex.dwLength = sizeof(msex); GlobalMemoryStatusEx( &msex ); V_VT(&v) = VT_UI8; V_UI8(&v) = msex.ullTotalPhys; + VariantChangeType(&v, &v, 0, VT_BSTR); IDxDiagContainerImpl_AddProp(pSubCont, ullPhysicalMemory, &v); + VariantClear(&v); info.dwOSVersionInfoSize = sizeof(info); GetVersionExW( &info ); - V_VT(&v) = VT_UI4; - V_UI4(&v) = info.dwMajorVersion; - IDxDiagContainerImpl_AddProp(pSubCont, dwOSMajorVersion, &v); - V_VT(&v) = VT_UI4; - V_UI4(&v) = info.dwMinorVersion; - IDxDiagContainerImpl_AddProp(pSubCont, dwOSMinorVersion, &v); - V_VT(&v) = VT_UI4; - V_UI4(&v) = info.dwBuildNumber; - IDxDiagContainerImpl_AddProp(pSubCont, dwOSBuildNumber, &v); - V_VT(&v) = VT_UI4; - V_UI4(&v) = info.dwPlatformId; - IDxDiagContainerImpl_AddProp(pSubCont, dwOSPlatformID, &v); + add_prop_ui4(pSubCont, dwOSMajorVersion, info.dwMajorVersion); + add_prop_ui4(pSubCont, dwOSMinorVersion, info.dwMinorVersion); + add_prop_ui4(pSubCont, dwOSBuildNumber, info.dwBuildNumber); + add_prop_ui4(pSubCont, dwOSPlatformID, info.dwPlatformId); return S_OK; } @@ -641,18 +610,12 @@ static HRESULT DXDiag_InitDXDiagDirectShowFiltersContainer(IDxDiagContainer* pSu LPBYTE pData = NULL; LPBYTE pCurrent = NULL; struct REG_RF* prrf = NULL; - VARIANT v_data; DWORD it; DWORD dwNOutputs = 0; DWORD dwNInputs = 0; - - V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(wszCatName); - hr = IDxDiagContainerImpl_AddProp(pSubCont, szCatName, &v); - VariantClear(&v); - V_VT(&v) = VT_BSTR; V_BSTR(&v) = SysAllocString(wszCatClsid); - hr = IDxDiagContainerImpl_AddProp(pSubCont, szClsidCat, &v); - VariantClear(&v); + add_prop_str(pSubCont, szCatName, wszCatName); + add_prop_str(pSubCont, szClsidCat, wszCatClsid); hr = IPropertyBag_Read(pPropFilterBag, wszFriendlyName, &v, 0); hr = IDxDiagContainerImpl_AddProp(pSubCont, szName, &v); @@ -668,14 +631,9 @@ static HRESULT DXDiag_InitDXDiagDirectShowFiltersContainer(IDxDiagContainer* pSu hr = SafeArrayAccessData(V_UNION(&v, parray), (LPVOID*) &pData); prrf = (struct REG_RF*) pData; pCurrent = pData; - - VariantInit(&v_data); - V_VT(&v_data) = VT_UI4; V_UI4(&v_data) = prrf->dwVersion; - hr = IDxDiagContainerImpl_AddProp(pSubCont, szName, &v_data); - VariantClear(&v_data); - V_VT(&v_data) = VT_UI4; V_UI4(&v_data) = prrf->dwMerit; - hr = IDxDiagContainerImpl_AddProp(pSubCont, dwMerit, &v_data); - VariantClear(&v_data); + + add_prop_ui4(pSubCont, szName, prrf->dwVersion); + add_prop_ui4(pSubCont, dwMerit, prrf->dwMerit); pCurrent += sizeof(struct REG_RF); for (it = 0; it < prrf->dwPins; ++it) { @@ -699,12 +657,8 @@ static HRESULT DXDiag_InitDXDiagDirectShowFiltersContainer(IDxDiagContainer* pSu } } - V_VT(&v_data) = VT_UI4; V_UI4(&v_data) = dwNInputs; - hr = IDxDiagContainerImpl_AddProp(pSubCont, dwInputs, &v_data); - VariantClear(&v_data); - V_VT(&v_data) = VT_UI4; V_UI4(&v_data) = dwNOutputs; - hr = IDxDiagContainerImpl_AddProp(pSubCont, dwOutputs, &v_data); - VariantClear(&v_data); + add_prop_ui4(pSubCont, dwInputs, dwNInputs); + add_prop_ui4(pSubCont, dwOutputs, dwNOutputs); SafeArrayUnaccessData(V_UNION(&v, parray)); VariantClear(&v); diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index 3a2776ccbbb..21342bb19b1 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -431,15 +431,19 @@ DEVMODEW * WINAPI GdiConvertToDevmodeW(const DEVMODEA *dmA) dmW = HeapAlloc(GetProcessHeap(), 0, dmW_size + dmA->dmDriverExtra); if (!dmW) return NULL; - MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmDeviceName, CCHDEVICENAME, + MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmDeviceName, -1, dmW->dmDeviceName, CCHDEVICENAME); /* copy slightly more, to avoid long computations */ memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion, dmA_size - CCHDEVICENAME); if (dmA_size >= FIELD_OFFSET(DEVMODEA, dmFormName) + CCHFORMNAME) { - MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmFormName, CCHFORMNAME, + if (dmA->dmFields & DM_FORMNAME) + MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmFormName, -1, dmW->dmFormName, CCHFORMNAME); + else + dmW->dmFormName[0] = 0; + if (dmA_size > FIELD_OFFSET(DEVMODEA, dmLogPixels)) memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA_size - FIELD_OFFSET(DEVMODEA, dmLogPixels)); } diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 1bfd97accb4..91e41e7ef39 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -800,9 +800,17 @@ INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name ) if (name) { - if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL)) + if (count) + { + res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL); + if (res == 0) + res = count; name[count-1] = 0; - res = strlen(name); + /* GetTextFaceA does NOT include the nul byte in the return count. */ + res--; + } + else + res = 0; } else res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL); @@ -825,12 +833,13 @@ INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name ) ret = WineEngGetTextFace(dc->gdiFont, count, name); else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC ))) { + INT n = strlenW(font->logfont.lfFaceName) + 1; if (name) { lstrcpynW( name, font->logfont.lfFaceName, count ); - ret = strlenW(name); + ret = min(count, n); } - else ret = strlenW(font->logfont.lfFaceName) + 1; + else ret = n; GDI_ReleaseObj( dc->hFont ); } release_dc_ptr( dc ); @@ -1410,6 +1419,9 @@ UINT WINAPI GetOutlineTextMetricsW( WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output); } + output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX); + output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY); + #define WDPTOLP(x) ((x<0)? \ (-abs(INTERNAL_XDSTOWS(dc, (x)))): \ (abs(INTERNAL_XDSTOWS(dc, (x))))) @@ -2898,13 +2910,13 @@ BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT a */ BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf ) { - ABC *abc; + ABC *abc, *abc_base; unsigned int i, size = sizeof(ABC) * (last - first + 1); BOOL ret; TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf); - abc = HeapAlloc( GetProcessHeap(), 0, size ); + abc = abc_base = HeapAlloc( GetProcessHeap(), 0, size ); if (!abc) return FALSE; ret = GetCharABCWidthsW( hdc, first, last, abc ); @@ -2917,7 +2929,7 @@ BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT a abcf->abcfC = abc->abcC; } } - HeapFree( GetProcessHeap(), 0, abc ); + HeapFree( GetProcessHeap(), 0, abc_base ); return ret; } diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 8bcb487c0b0..731b1c58706 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -328,7 +328,7 @@ struct tagGdiFont { INT orientation; FONT_DESC font_desc; LONG aveWidth, ppem; - float scale_y; + double scale_y; SHORT yMax; SHORT yMin; DWORD ntmFlags; @@ -360,8 +360,6 @@ static const WCHAR defSerif[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o' static const WCHAR defSans[] = {'A','r','i','a','l','\0'}; static const WCHAR defFixed[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'}; -static const WCHAR RegularW[] = {'R','e','g','u','l','a','r','\0'}; - static const WCHAR fontsW[] = {'\\','f','o','n','t','s','\0'}; static const WCHAR win9x_font_reg_key[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', 'W','i','n','d','o','w','s','\\', @@ -809,7 +807,7 @@ static inline BOOL is_win9x(void) in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed. It fails if the integer part of the float number is greater than SHORT_MAX. */ -static inline FT_Fixed FT_FixedFromFloat(float f) +static inline FT_Fixed FT_FixedFromFloat(double f) { short value = f; unsigned short fract = (f - value) * 0xFFFF; @@ -1008,7 +1006,7 @@ static void LoadSubstList(void) /* Win 2000 doesn't allow mapping between different charsets or mapping of DEFAULT_CHARSET */ - if((psub->to.charset != psub->from.charset) || + if ((psub->from.charset && psub->to.charset != psub->from.charset) || psub->to.charset == DEFAULT_CHARSET) { HeapFree(GetProcessHeap(), 0, psub->to.name); HeapFree(GetProcessHeap(), 0, psub->from.name); @@ -1945,7 +1943,7 @@ static void update_reg_entries(void) face = LIST_ENTRY(face_elem_ptr, Face, entry); if(!face->external) continue; len = len_fam; - if(strcmpiW(face->StyleName, RegularW)) + if (!(face->ntmFlags & NTM_REGULAR)) len = len_fam + strlenW(face->StyleName) + 1; valueW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); strcpyW(valueW, family->FamilyName); @@ -2124,84 +2122,144 @@ static const struct nls_update_font_list UINT ansi_cp, oem_cp; const char *oem, *fixed, *system; const char *courier, *serif, *small, *sserif; - /* these are for font substitute */ + /* these are for font substitutes */ const char *shelldlg, *tmsrmn; + const char *fixed_0, *system_0, *courier_0, *serif_0, *small_0, *sserif_0, + *helv_0, *tmsrmn_0; + const struct subst + { + const char *from, *to; + } arial_0, courier_new_0, times_new_roman_0; } nls_update_font_list[] = { /* Latin 1 (United States) */ { 1252, 437, "vgaoem.fon", "vgafix.fon", "vgasys.fon", "coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "Tahoma","Times New Roman", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + { 0 }, { 0 }, { 0 } }, /* Latin 1 (Multilingual) */ { 1252, 850, "vga850.fon", "vgafix.fon", "vgasys.fon", "coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "Tahoma","Times New Roman", /* FIXME unverified */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + { 0 }, { 0 }, { 0 } }, /* Eastern Europe */ { 1250, 852, "vga852.fon", "vgafixe.fon", "vgasyse.fon", "couree.fon", "serifee.fon", "smallee.fon", "sserifee.fon", "Tahoma","Times New Roman", /* FIXME unverified */ + "Fixedsys,238", "System,238", + "Courier New,238", "MS Serif,238", "Small Fonts,238", + "MS Sans Serif,238", "MS Sans Serif,238", "MS Serif,238", + { "Arial CE,0", "Arial,238" }, + { "Courier New CE,0", "Courier New,238" }, + { "Times New Roman CE,0", "Times New Roman,238" } }, /* Cyrillic */ { 1251, 866, "vga866.fon", "vgafixr.fon", "vgasysr.fon", "courer.fon", "serifer.fon", "smaller.fon", "sserifer.fon", "Tahoma","Times New Roman", /* FIXME unverified */ + "Fixedsys,204", "System,204", + "Courier New,204", "MS Serif,204", "Small Fonts,204", + "MS Sans Serif,204", "MS Sans Serif,204", "MS Serif,204", + { "Arial Cyr,0", "Arial,204" }, + { "Courier New Cyr,0", "Courier New,204" }, + { "Times New Roman Cyr,0", "Times New Roman,204" } }, /* Greek */ { 1253, 737, "vga869.fon", "vgafixg.fon", "vgasysg.fon", "coureg.fon", "serifeg.fon", "smalleg.fon", "sserifeg.fon", "Tahoma","Times New Roman", /* FIXME unverified */ + "Fixedsys,161", "System,161", + "Courier New,161", "MS Serif,161", "Small Fonts,161", + "MS Sans Serif,161", "MS Sans Serif,161", "MS Serif,161", + { "Arial Greek,0", "Arial,161" }, + { "Courier New Greek,0", "Courier New,161" }, + { "Times New Roman Greek,0", "Times New Roman,161" } }, /* Turkish */ { 1254, 857, "vga857.fon", "vgafixt.fon", "vgasyst.fon", "couret.fon", "serifet.fon", "smallet.fon", "sserifet.fon", "Tahoma","Times New Roman", /* FIXME unverified */ + "Fixedsys,162", "System,162", + "Courier New,162", "MS Serif,162", "Small Fonts,162", + "MS Sans Serif,162", "MS Sans Serif,162", "MS Serif,162", + { "Arial Tur,0", "Arial,162" }, + { "Courier New Tur,0", "Courier New,162" }, + { "Times New Roman Tur,0", "Times New Roman,162" } }, /* Hebrew */ { 1255, 862, "vgaoem.fon", "vgaf1255.fon", "vgas1255.fon", "coue1255.fon", "sere1255.fon", "smae1255.fon", "ssee1255.fon", "Tahoma","Times New Roman", /* FIXME unverified */ + "Fixedsys,177", "System,177", + "Courier New,177", "MS Serif,177", "Small Fonts,177", + "MS Sans Serif,177", "MS Sans Serif,177", "MS Serif,177", + { 0 }, { 0 }, { 0 } }, /* Arabic */ { 1256, 720, "vgaoem.fon", "vgaf1256.fon", "vgas1256.fon", "coue1256.fon", "sere1256.fon", "smae1256.fon", "ssee1256.fon", "Tahoma","Times New Roman", /* FIXME unverified */ + "Fixedsys,178", "System,178", + "Courier New,178", "MS Serif,178", "Small Fonts,178", + "MS Sans Serif,178", "MS Sans Serif,178", "MS Serif,178", + { 0 }, { 0 }, { 0 } }, /* Baltic */ { 1257, 775, "vga775.fon", "vgaf1257.fon", "vgas1257.fon", "coue1257.fon", "sere1257.fon", "smae1257.fon", "ssee1257.fon", "Tahoma","Times New Roman", /* FIXME unverified */ + "Fixedsys,186", "System,186", + "Courier New,186", "MS Serif,186", "Small Fonts,186", + "MS Sans Serif,186", "MS Sans Serif,186", "MS Serif,186", + { "Arial Baltic,0", "Arial,186" }, + { "Courier New Baltic,0", "Courier New,186" }, + { "Times New Roman Baltic,0", "Times New Roman,186" } }, /* Vietnamese */ { 1258, 1258, "vga850.fon", "vgafix.fon", "vgasys.fon", "coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "Tahoma","Times New Roman", /* FIXME unverified */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + { 0 }, { 0 }, { 0 } }, /* Thai */ { 874, 874, "vga850.fon", "vgaf874.fon", "vgas874.fon", "coure.fon", "serife.fon", "smalle.fon", "ssee874.fon", "Tahoma","Times New Roman", /* FIXME unverified */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + { 0 }, { 0 }, { 0 } }, /* Japanese */ { 932, 932, "vga932.fon", "jvgafix.fon", "jvgasys.fon", "coure.fon", "serife.fon", "jsmalle.fon", "sserife.fon", "MS UI Gothic","MS Serif", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + { 0 }, { 0 }, { 0 } }, /* Chinese Simplified */ { 936, 936, "vga936.fon", "svgafix.fon", "svgasys.fon", "coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "Tahoma", "Times New Roman", /* FIXME unverified */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + { 0 }, { 0 }, { 0 } }, /* Korean */ { 949, 949, "vga949.fon", "hvgafix.fon", "hvgasys.fon", "coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "Gulim", "Batang", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + { 0 }, { 0 }, { 0 } }, /* Chinese Traditional */ { 950, 950, "vga950.fon", "cvgafix.fon", "cvgasys.fon", "coure.fon", "serife.fon", "smalle.fon", "sserife.fon", "PMingLiU", "MingLiU", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + { 0 }, { 0 }, { 0 } } }; @@ -2248,12 +2306,21 @@ static void add_font_list(HKEY hkey, const struct nls_update_font_list *fl) RegSetValueExA(hkey, "Small Fonts", 0, REG_SZ, (const BYTE *)fl->small, strlen(fl->small)+1); } +static void set_value_key(HKEY hkey, const char *name, const char *value) +{ + if (value) + RegSetValueExA(hkey, name, 0, REG_SZ, (const BYTE *)value, strlen(value) + 1); + else if (name) + RegDeleteValueA(hkey, name); +} + static void update_font_info(void) { char buf[40], cpbuf[40]; DWORD len, type; HKEY hkey = 0; UINT i, ansi_cp = 0, oem_cp = 0; + BOOL done = FALSE; if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\Fonts", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL) != ERROR_SUCCESS) return; @@ -2285,11 +2352,11 @@ static void update_font_info(void) for (i = 0; i < sizeof(nls_update_font_list)/sizeof(nls_update_font_list[0]); i++) { + HKEY hkey; + if (nls_update_font_list[i].ansi_cp == ansi_cp && nls_update_font_list[i].oem_cp == oem_cp) { - HKEY hkey; - hkey = create_config_fonts_registry_key(); RegSetValueExA(hkey, "OEMFONT.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].oem, strlen(nls_update_font_list[i].oem)+1); RegSetValueExA(hkey, "FIXEDFON.FON", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].fixed, strlen(nls_update_font_list[i].fixed)+1); @@ -2310,12 +2377,38 @@ static void update_font_info(void) strlen(nls_update_font_list[i].shelldlg)+1); RegSetValueExA(hkey, "Tms Rmn", 0, REG_SZ, (const BYTE *)nls_update_font_list[i].tmsrmn, strlen(nls_update_font_list[i].tmsrmn)+1); + + set_value_key(hkey, "Fixedsys,0", nls_update_font_list[i].fixed_0); + set_value_key(hkey, "System,0", nls_update_font_list[i].system_0); + set_value_key(hkey, "Courier,0", nls_update_font_list[i].courier_0); + set_value_key(hkey, "MS Serif,0", nls_update_font_list[i].serif_0); + set_value_key(hkey, "Small Fonts,0", nls_update_font_list[i].small_0); + set_value_key(hkey, "MS Sans Serif,0", nls_update_font_list[i].sserif_0); + set_value_key(hkey, "Helv,0", nls_update_font_list[i].helv_0); + set_value_key(hkey, "Tms Rmn,0", nls_update_font_list[i].tmsrmn_0); + + set_value_key(hkey, nls_update_font_list[i].arial_0.from, nls_update_font_list[i].arial_0.to); + set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, nls_update_font_list[i].courier_new_0.to); + set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, nls_update_font_list[i].times_new_roman_0.to); + + RegCloseKey(hkey); + } + done = TRUE; + } + else + { + /* Delete the FontSubstitutes from other locales */ + if (!RegCreateKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", &hkey )) + { + set_value_key(hkey, nls_update_font_list[i].arial_0.from, NULL); + set_value_key(hkey, nls_update_font_list[i].courier_new_0.from, NULL); + set_value_key(hkey, nls_update_font_list[i].times_new_roman_0.from, NULL); RegCloseKey(hkey); } - return; } } - FIXME("there is no font defaults for codepages %u,%u\n", ansi_cp, oem_cp); + if (!done) + FIXME("there is no font defaults for codepages %u,%u\n", ansi_cp, oem_cp); } @@ -2588,11 +2681,11 @@ static LONG calc_ppem_for_height(FT_Face ft_face, LONG height) if(height > 0) { if(pOS2->usWinAscent + pOS2->usWinDescent == 0) - ppem = ft_face->units_per_EM * height / - (pHori->Ascender - pHori->Descender); + ppem = MulDiv(ft_face->units_per_EM, height, + pHori->Ascender - pHori->Descender); else - ppem = ft_face->units_per_EM * height / - (pOS2->usWinAscent + pOS2->usWinDescent); + ppem = MulDiv(ft_face->units_per_EM, height, + pOS2->usWinAscent + pOS2->usWinDescent); } else ppem = -height; @@ -2692,6 +2785,7 @@ static FT_Face OpenFontFace(GdiFont *font, Face *face, LONG width, LONG height) font->ppem = load_VDMX(font, height); if(font->ppem == 0) font->ppem = calc_ppem_for_height(ft_face, height); + TRACE("height %d => ppem %d\n", height, font->ppem); if((err = pFT_Set_Pixel_Sizes(ft_face, 0, font->ppem)) != 0) WARN("FT_Set_Pixel_Sizes %d, %d rets %x\n", 0, font->ppem, err); @@ -3149,6 +3243,7 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) LOGFONTW lf; CHARSETINFO csi; HFONTLIST *hflist; + FontSubst *psub = NULL; EnterCriticalSection( &freetype_cs ); @@ -3177,6 +3272,11 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) lf.lfWeight, lf.lfPitchAndFamily, lf.lfCharSet, lf.lfOrientation, lf.lfEscapement); + TRACE("DC transform %f %f %f %f %f %f\n", + dc->xformWorld2Vport.eM11, dc->xformWorld2Vport.eM12, + dc->xformWorld2Vport.eM21, dc->xformWorld2Vport.eM22, + dc->xformWorld2Vport.eDx, dc->xformWorld2Vport.eDy); + /* 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); @@ -3200,14 +3300,13 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) ret = alloc_font(); - memcpy(&ret->font_desc.matrix, &dc->xformWorld2Vport, sizeof(FMAT2)); - ret->font_desc.lf = lf; - ret->font_desc.can_use_bitmap = can_use_bitmap; - calc_hash(&ret->font_desc); - hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist)); - hflist->hfont = hfont; - list_add_head(&ret->hfontlist, &hflist->entry); - + memcpy(&ret->font_desc.matrix, &dc->xformWorld2Vport, sizeof(FMAT2)); + ret->font_desc.lf = lf; + ret->font_desc.can_use_bitmap = can_use_bitmap; + calc_hash(&ret->font_desc); + hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist)); + hflist->hfont = hfont; + list_add_head(&ret->hfontlist, &hflist->entry); /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to SYMBOL_CHARSET so that Symbol gets picked irrespective of the @@ -3231,7 +3330,6 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) family = NULL; if(lf.lfFaceName[0] != '\0') { - FontSubst *psub; SYSTEM_LINKS *font_link; CHILD_FONT *font_link_entry; LPWSTR FaceName = lf.lfFaceName; @@ -3247,9 +3345,10 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) psub = get_font_subst(&font_subst_list, FaceName, lf.lfCharSet); if(psub) { - TRACE("substituting %s -> %s\n", debugstr_w(FaceName), - debugstr_w(psub->to.name)); - strcpyW(FaceName, psub->to.name); + TRACE("substituting %s,%d -> %s,%d\n", debugstr_w(FaceName), lf.lfCharSet, + debugstr_w(psub->to.name), (psub->to.charset != -1) ? psub->to.charset : lf.lfCharSet); + if (psub->to.charset != -1) + lf.lfCharSet = psub->to.charset; } /* We want a match on name and charset or just name if @@ -3260,7 +3359,9 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) */ LIST_FOR_EACH(family_elem_ptr, &font_list) { family = LIST_ENTRY(family_elem_ptr, Family, entry); - if(!strcmpiW(family->FamilyName, FaceName)) { + if (!strcmpiW(family->FamilyName, FaceName) || + (psub && !strcmpiW(family->FamilyName, psub->to.name))) + { LIST_FOR_EACH(face_elem_ptr, &family->faces) { face = LIST_ENTRY(face_elem_ptr, Face, entry); if((csi.fs.fsCsb[0] & (face->fs.fsCsb[0] | face->fs_links.fsCsb[0])) || !csi.fs.fsCsb[0]) @@ -3294,6 +3395,8 @@ GdiFont *WineEngCreateFontInstance(DC *dc, HFONT hfont) } } + psub = NULL; /* substitution is no more relevant */ + /* If requested charset was DEFAULT_CHARSET then try using charset corresponding to the current ansi codepage */ if (!csi.fs.fsCsb[0] || lf.lfWeight == FW_DONTCARE) @@ -3378,8 +3481,7 @@ found: it = lf.lfItalic ? 1 : 0; bd = lf.lfWeight > 550 ? 1 : 0; - height = GDI_ROUND( (double)lf.lfHeight * dc->xformWorld2Vport.eM22 ); - height = lf.lfHeight < 0 ? -abs(height) : abs(height); + height = lf.lfHeight; face = best = best_bitmap = NULL; LIST_FOR_EACH_ENTRY(face, &family->faces, Face, entry) @@ -3478,7 +3580,7 @@ found: } ret->orientation = FT_IS_SCALABLE(ret->ft_face) ? lf.lfOrientation : 0; - ret->name = strdupW(family->FamilyName); + ret->name = psub ? strdupW(psub->from.name) : strdupW(family->FamilyName); ret->underline = lf.lfUnderline ? 0xff : 0; ret->strikeout = lf.lfStrikeOut ? 0xff : 0; create_child_font_list(ret); @@ -4156,6 +4258,18 @@ DWORD WineEngGetGlyphIndices(GdiFont *font, LPCWSTR lpstr, INT count, return count; } +static inline BOOL is_identity_FMAT2(const FMAT2 *matrix) +{ + static const FMAT2 identity = { 1.0, 0.0, 0.0, 1.0 }; + return !memcmp(matrix, &identity, sizeof(FMAT2)); +} + +static inline BOOL is_identity_MAT2(const MAT2 *matrix) +{ + static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} }; + return !memcmp(matrix, &identity, sizeof(MAT2)); +} + /************************************************************* * WineEngGetGlyphOutline * @@ -4178,16 +4292,19 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, INT left, right, top = 0, bottom = 0, adv, lsb, bbx; FT_Angle angle = 0; FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; - float widthRatio = 1.0; + double widthRatio = 1.0; FT_Matrix transMat = identityMat; BOOL needsTransform = FALSE; BOOL tategaki = (font->GSUB_Table != NULL); UINT original_index; - TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm, buflen, buf, lpmat); + TRACE("font transform %f %f %f %f\n", + font->font_desc.matrix.eM11, font->font_desc.matrix.eM12, + font->font_desc.matrix.eM21, font->font_desc.matrix.eM22); + EnterCriticalSection( &freetype_cs ); if(format & GGO_GLYPH_INDEX) { @@ -4209,8 +4326,13 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm, font->gmsize * sizeof(GM*)); } else { - if(format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL && FONT_GM(font,original_index)->init ) { + if (format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL && + FONT_GM(font,original_index)->init && (!lpmat || is_identity_MAT2(lpmat))) + { *lpgm = FONT_GM(font,original_index)->gm; + TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY, + wine_dbgstr_point(&lpgm->gmptGlyphOrigin), + lpgm->gmCellIncX, lpgm->gmCellIncY); LeaveCriticalSection( &freetype_cs ); return 1; /* FIXME */ } @@ -4231,23 +4353,28 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, } /* Scaling factor */ - if (font->aveWidth && font->potm) + if (font->aveWidth) { - widthRatio = (float)font->aveWidth * font->font_desc.matrix.eM11; - widthRatio /= (float)font->potm->otmTextMetrics.tmAveCharWidth; + TEXTMETRICW tm; + + WineEngGetTextMetrics(font, &tm); + + widthRatio = (double)font->aveWidth; + widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth; } else widthRatio = font->scale_y; - left = (INT)(ft_face->glyph->metrics.horiBearingX * widthRatio) & -64; - right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) * widthRatio + 63) & -64; + left = (INT)(ft_face->glyph->metrics.horiBearingX) & -64; + right = (INT)((ft_face->glyph->metrics.horiBearingX + ft_face->glyph->metrics.width) + 63) & -64; - adv = (INT)((ft_face->glyph->metrics.horiAdvance * widthRatio) + 63) >> 6; + adv = (INT)((ft_face->glyph->metrics.horiAdvance) + 63) >> 6; lsb = left >> 6; bbx = (right - left) >> 6; /* Scaling transform */ - if(font->aveWidth) { + if (widthRatio != 1.0 || font->scale_y != 1.0) + { FT_Matrix scaleMat; scaleMat.xx = FT_FixedFromFloat(widthRatio); scaleMat.xy = 0; @@ -4274,7 +4401,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, if(font->orientation && !tategaki) { FT_Matrix rotationMat; FT_Vector vecAngle; - angle = FT_FixedFromFloat((float)font->orientation / 10.0); + angle = FT_FixedFromFloat((double)font->orientation / 10.0); pFT_Vector_Unit(&vecAngle, angle); rotationMat.xx = vecAngle.x; rotationMat.xy = -vecAngle.y; @@ -4285,8 +4412,21 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, needsTransform = TRUE; } + /* World transform */ + if (!is_identity_FMAT2(&font->font_desc.matrix)) + { + FT_Matrix worldMat; + worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11); + worldMat.xy = FT_FixedFromFloat(font->font_desc.matrix.eM21); + worldMat.yx = FT_FixedFromFloat(font->font_desc.matrix.eM12); + worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22); + pFT_Matrix_Multiply(&worldMat, &transMat); + needsTransform = TRUE; + } + /* Extra transformation specified by caller */ - if (lpmat) { + if (lpmat && !is_identity_MAT2(lpmat)) + { FT_Matrix extraMat; extraMat.xx = FT_FixedFromFIXED(lpmat->eM11); extraMat.xy = FT_FixedFromFIXED(lpmat->eM21); @@ -4333,7 +4473,7 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, vec.x = ft_face->glyph->metrics.horiAdvance; vec.y = 0; pFT_Vector_Transform(&vec, &transMat); - lpgm->gmCellIncX = (vec.x+63) >> 6; + adv = lpgm->gmCellIncX = (vec.x+63) >> 6; lpgm->gmCellIncY = -((vec.y+63) >> 6); } lpgm->gmBlackBoxX = (right - left) >> 6; @@ -4341,7 +4481,12 @@ DWORD WineEngGetGlyphOutline(GdiFont *incoming_font, UINT glyph, UINT format, lpgm->gmptGlyphOrigin.x = left >> 6; lpgm->gmptGlyphOrigin.y = top >> 6; - if(format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) + TRACE("%u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY, + wine_dbgstr_point(&lpgm->gmptGlyphOrigin), + lpgm->gmCellIncX, lpgm->gmCellIncY); + + if ((format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) && + (!lpmat || is_identity_MAT2(lpmat))) /* don't cache custom transforms */ { FONT_GM(font,original_index)->gm = *lpgm; FONT_GM(font,original_index)->adv = adv; @@ -4749,24 +4894,83 @@ static BOOL get_bitmap_text_metrics(GdiFont *font) static void scale_font_metrics(const GdiFont *font, LPTEXTMETRICW ptm) { - float scale_x; + double scale_x, scale_y; if (font->aveWidth) { - scale_x = (float)font->aveWidth * font->font_desc.matrix.eM11; - scale_x /= (float)font->potm->otmTextMetrics.tmAveCharWidth; + scale_x = (double)font->aveWidth; + scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth; } else scale_x = font->scale_y; - ptm->tmHeight = (float)ptm->tmHeight * font->scale_y; - ptm->tmAscent = (float)ptm->tmAscent * font->scale_y; - ptm->tmDescent = (float)ptm->tmDescent * font->scale_y; - ptm->tmInternalLeading = (float)ptm->tmInternalLeading * font->scale_y; - ptm->tmExternalLeading = (float)ptm->tmExternalLeading * font->scale_y; + scale_x *= fabs(font->font_desc.matrix.eM11); + scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22); + +#define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x)) +#define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y)) - ptm->tmAveCharWidth = (float)ptm->tmAveCharWidth * scale_x; - ptm->tmMaxCharWidth = (float)ptm->tmMaxCharWidth * scale_x; + SCALE_Y(ptm->tmHeight); + SCALE_Y(ptm->tmAscent); + SCALE_Y(ptm->tmDescent); + SCALE_Y(ptm->tmInternalLeading); + SCALE_Y(ptm->tmExternalLeading); + SCALE_Y(ptm->tmOverhang); + + SCALE_X(ptm->tmAveCharWidth); + SCALE_X(ptm->tmMaxCharWidth); + +#undef SCALE_X +#undef SCALE_Y +} + +static void scale_outline_font_metrics(const GdiFont *font, OUTLINETEXTMETRICW *potm) +{ + double scale_x, scale_y; + + if (font->aveWidth) + { + scale_x = (double)font->aveWidth; + scale_x /= (double)font->potm->otmTextMetrics.tmAveCharWidth; + } + else + scale_x = font->scale_y; + + scale_x *= fabs(font->font_desc.matrix.eM11); + scale_y = font->scale_y * fabs(font->font_desc.matrix.eM22); + + scale_font_metrics(font, &potm->otmTextMetrics); + +#define SCALE_X(x) (x) = GDI_ROUND((double)(x) * (scale_x)) +#define SCALE_Y(y) (y) = GDI_ROUND((double)(y) * (scale_y)) + + SCALE_Y(potm->otmAscent); + SCALE_Y(potm->otmDescent); + SCALE_Y(potm->otmLineGap); + SCALE_Y(potm->otmsCapEmHeight); + SCALE_Y(potm->otmsXHeight); + SCALE_Y(potm->otmrcFontBox.top); + SCALE_Y(potm->otmrcFontBox.bottom); + SCALE_X(potm->otmrcFontBox.left); + SCALE_X(potm->otmrcFontBox.right); + SCALE_Y(potm->otmMacAscent); + SCALE_Y(potm->otmMacDescent); + SCALE_Y(potm->otmMacLineGap); + SCALE_X(potm->otmptSubscriptSize.x); + SCALE_Y(potm->otmptSubscriptSize.y); + SCALE_X(potm->otmptSubscriptOffset.x); + SCALE_Y(potm->otmptSubscriptOffset.y); + SCALE_X(potm->otmptSuperscriptSize.x); + SCALE_Y(potm->otmptSuperscriptSize.y); + SCALE_X(potm->otmptSuperscriptOffset.x); + SCALE_Y(potm->otmptSuperscriptOffset.y); + SCALE_Y(potm->otmsStrikeoutSize); + SCALE_Y(potm->otmsStrikeoutPosition); + SCALE_Y(potm->otmsUnderscoreSize); + SCALE_Y(potm->otmsUnderscorePosition); + +#undef SCALE_X +#undef SCALE_Y } /************************************************************* @@ -4825,7 +5029,7 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize, if(cbSize >= font->potm->otmSize) { memcpy(potm, font->potm, font->potm->otmSize); - scale_font_metrics(font, &potm->otmTextMetrics); + scale_outline_font_metrics(font, potm); } LeaveCriticalSection( &freetype_cs ); return font->potm->otmSize; @@ -4849,7 +5053,7 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize, needed += lenfam; /* length of otmpFaceName */ - if(!strcasecmp(ft_face->style_name, "regular")) { + if ((ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) == 0) { needed += lenfam; /* just the family name */ } else { needed += lenfam + lensty; /* family + " " + style */ @@ -4996,7 +5200,6 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize, } TM.tmCharSet = font->charset; -#undef TM font->potm->otmFiller = 0; memcpy(&font->potm->otmPanoseNumber, pOS2->panose, PANOSE_COUNT); @@ -5015,9 +5218,9 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize, font->potm->otmrcFontBox.right = (pFT_MulFix(ft_face->bbox.xMax, x_scale) + 32) >> 6; font->potm->otmrcFontBox.top = (pFT_MulFix(ft_face->bbox.yMax, y_scale) + 32) >> 6; font->potm->otmrcFontBox.bottom = (pFT_MulFix(ft_face->bbox.yMin, y_scale) + 32) >> 6; - font->potm->otmMacAscent = 0; /* where do these come from ? */ - font->potm->otmMacDescent = 0; - font->potm->otmMacLineGap = 0; + font->potm->otmMacAscent = TM.tmAscent; + font->potm->otmMacDescent = -TM.tmDescent; + font->potm->otmMacLineGap = font->potm->otmLineGap; font->potm->otmusMinimumPPEM = 0; /* TT Header */ font->potm->otmptSubscriptSize.x = (pFT_MulFix(pOS2->ySubscriptXSize, x_scale) + 32) >> 6; font->potm->otmptSubscriptSize.y = (pFT_MulFix(pOS2->ySubscriptYSize, y_scale) + 32) >> 6; @@ -5036,6 +5239,7 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize, font->potm->otmsUnderscoreSize = (pFT_MulFix(pPost->underlineThickness, y_scale) + 32) >> 6; font->potm->otmsUnderscorePosition = (pFT_MulFix(pPost->underlinePosition, y_scale) + 32) >> 6; } +#undef TM /* otmp* members should clearly have type ptrdiff_t, but M$ knows best */ cp = (char*)font->potm + sizeof(*font->potm); @@ -5047,7 +5251,7 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize, cp += lensty; font->potm->otmpFaceName = (LPSTR)(cp - (char*)font->potm); strcpyW((WCHAR*)cp, family_nameW); - if(strcasecmp(ft_face->style_name, "regular")) { + if (ft_face->style_flags & (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) { strcatW((WCHAR*)cp, spaceW); strcatW((WCHAR*)cp, style_nameW); cp += lenfam + lensty; @@ -5062,7 +5266,7 @@ UINT WineEngGetOutlineTextMetrics(GdiFont *font, UINT cbSize, if(potm && needed <= cbSize) { memcpy(potm, font->potm, font->potm->otmSize); - scale_font_metrics(font, &potm->otmTextMetrics); + scale_outline_font_metrics(font, potm); } end: @@ -5365,11 +5569,12 @@ DWORD WineEngGetFontData(GdiFont *font, DWORD table, DWORD offset, LPVOID buf, */ INT WineEngGetTextFace(GdiFont *font, INT count, LPWSTR str) { + INT n = strlenW(font->name) + 1; if(str) { lstrcpynW(str, font->name, count); - return strlenW(font->name); + return min(count, n); } else - return strlenW(font->name) + 1; + return n; } UINT WineEngGetTextCharsetInfo(GdiFont *font, LPFONTSIGNATURE fs, DWORD flags) diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 710148af2cd..868661c0d09 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -30,6 +30,7 @@ #include "wine/test.h" +#define near_match(a, b) (abs((a) - (b)) <= 4) #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) LONG (WINAPI *pGdiGetCharDimensions)(HDC hdc, LPTEXTMETRICW lptm, LONG *height); @@ -158,6 +159,30 @@ static INT CALLBACK font_enum_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DW return 1; /* continue enumeration */ } +static void compare_tm(const TEXTMETRICA *tm, const TEXTMETRICA *otm) +{ + ok(tm->tmHeight == otm->tmHeight, "tmHeight %d != %d\n", tm->tmHeight, otm->tmHeight); + ok(tm->tmAscent == otm->tmAscent, "tmAscent %d != %d\n", tm->tmAscent, otm->tmAscent); + ok(tm->tmDescent == otm->tmDescent, "tmDescent %d != %d\n", tm->tmDescent, otm->tmDescent); + ok(tm->tmInternalLeading == otm->tmInternalLeading, "tmInternalLeading %d != %d\n", tm->tmInternalLeading, otm->tmInternalLeading); + ok(tm->tmExternalLeading == otm->tmExternalLeading, "tmExternalLeading %d != %d\n", tm->tmExternalLeading, otm->tmExternalLeading); + ok(tm->tmAveCharWidth == otm->tmAveCharWidth, "tmAveCharWidth %d != %d\n", tm->tmAveCharWidth, otm->tmAveCharWidth); + ok(tm->tmMaxCharWidth == otm->tmMaxCharWidth, "tmMaxCharWidth %d != %d\n", tm->tmMaxCharWidth, otm->tmMaxCharWidth); + ok(tm->tmWeight == otm->tmWeight, "tmWeight %d != %d\n", tm->tmWeight, otm->tmWeight); + ok(tm->tmOverhang == otm->tmOverhang, "tmOverhang %d != %d\n", tm->tmOverhang, otm->tmOverhang); + ok(tm->tmDigitizedAspectX == otm->tmDigitizedAspectX, "tmDigitizedAspectX %d != %d\n", tm->tmDigitizedAspectX, otm->tmDigitizedAspectX); + ok(tm->tmDigitizedAspectY == otm->tmDigitizedAspectY, "tmDigitizedAspectY %d != %d\n", tm->tmDigitizedAspectY, otm->tmDigitizedAspectY); + ok(tm->tmFirstChar == otm->tmFirstChar, "tmFirstChar %d != %d\n", tm->tmFirstChar, otm->tmFirstChar); + ok(tm->tmLastChar == otm->tmLastChar, "tmLastChar %d != %d\n", tm->tmLastChar, otm->tmLastChar); + ok(tm->tmDefaultChar == otm->tmDefaultChar, "tmDefaultChar %d != %d\n", tm->tmDefaultChar, otm->tmDefaultChar); + ok(tm->tmBreakChar == otm->tmBreakChar, "tmBreakChar %d != %d\n", tm->tmBreakChar, otm->tmBreakChar); + ok(tm->tmItalic == otm->tmItalic, "tmItalic %d != %d\n", tm->tmItalic, otm->tmItalic); + ok(tm->tmUnderlined == otm->tmUnderlined, "tmUnderlined %d != %d\n", tm->tmUnderlined, otm->tmUnderlined); + ok(tm->tmStruckOut == otm->tmStruckOut, "tmStruckOut %d != %d\n", tm->tmStruckOut, otm->tmStruckOut); + ok(tm->tmPitchAndFamily == otm->tmPitchAndFamily, "tmPitchAndFamily %d != %d\n", tm->tmPitchAndFamily, otm->tmPitchAndFamily); + ok(tm->tmCharSet == otm->tmCharSet, "tmCharSet %d != %d\n", tm->tmCharSet, otm->tmCharSet); +} + static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight, LONG lfWidth, const char *test_str, INT test_str_len, const TEXTMETRICA *tm_orig, @@ -166,9 +191,11 @@ static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight, { HFONT old_hfont; LOGFONTA lf; + OUTLINETEXTMETRIC otm; TEXTMETRICA tm; SIZE size; INT width_of_A, cx, cy; + UINT ret; if (!hfont) return; @@ -177,35 +204,75 @@ static void test_font_metrics(HDC hdc, HFONT hfont, LONG lfHeight, old_hfont = SelectObject(hdc, hfont); - GetTextMetricsA(hdc, &tm); + if (GetOutlineTextMetricsA(hdc, 0, NULL)) + { + otm.otmSize = sizeof(otm) / 2; + ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm); + ok(ret == sizeof(otm)/2 /* XP */ || + ret == 1 /* Win9x */, "expected sizeof(otm)/2, got %u\n", ret); + + memset(&otm, 0x1, sizeof(otm)); + otm.otmSize = sizeof(otm); + ret = GetOutlineTextMetricsA(hdc, otm.otmSize, &otm); + ok(ret == sizeof(otm) /* XP */ || + ret == 1 /* Win9x */, "expected sizeof(otm), got %u\n", ret); + + memset(&tm, 0x2, sizeof(tm)); + ret = GetTextMetricsA(hdc, &tm); + ok(ret, "GetTextMetricsA failed\n"); + /* the structure size is aligned */ + if (memcmp(&tm, &otm.otmTextMetrics, FIELD_OFFSET(TEXTMETRICA, tmCharSet) + 1)) + { + ok(0, "tm != otm\n"); + compare_tm(&tm, &otm.otmTextMetrics); + } + + tm = otm.otmTextMetrics; +if (0) /* these metrics are scaled too, but with rounding errors */ +{ + ok(otm.otmAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmAscent, tm.tmAscent); + ok(otm.otmDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmDescent, -tm.tmDescent); +} + ok(otm.otmMacAscent == tm.tmAscent, "ascent %d != %d\n", otm.otmMacAscent, tm.tmAscent); + ok(otm.otmDescent < 0, "otm.otmDescent should be < 0\n"); + ok(otm.otmMacDescent < 0, "otm.otmMacDescent should be < 0\n"); + ok(tm.tmDescent > 0, "tm.tmDescent should be > 0\n"); + ok(otm.otmMacDescent == -tm.tmDescent, "descent %d != %d\n", otm.otmMacDescent, -tm.tmDescent); + ok(otm.otmEMSquare == 2048, "expected 2048, got %d\n", otm.otmEMSquare); + } + else + { + ret = GetTextMetricsA(hdc, &tm); + ok(ret, "GetTextMetricsA failed\n"); + } cx = tm.tmAveCharWidth / tm_orig->tmAveCharWidth; cy = tm.tmHeight / tm_orig->tmHeight; ok(cx == scale_x && cy == scale_y, "expected scale_x %d, scale_y %d, got cx %d, cy %d\n", scale_x, scale_y, cx, cy); - ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "%d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y); - ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "%d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y); - ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "%d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y); - ok(tm.tmAveCharWidth == tm_orig->tmAveCharWidth * scale_x, "%d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x); - ok(tm.tmMaxCharWidth == tm_orig->tmMaxCharWidth * scale_x, "%d != %d\n", tm.tmAveCharWidth, tm_orig->tmMaxCharWidth * scale_x); + ok(tm.tmHeight == tm_orig->tmHeight * scale_y, "height %d != %d\n", tm.tmHeight, tm_orig->tmHeight * scale_y); + ok(tm.tmAscent == tm_orig->tmAscent * scale_y, "ascent %d != %d\n", tm.tmAscent, tm_orig->tmAscent * scale_y); + ok(tm.tmDescent == tm_orig->tmDescent * scale_y, "descent %d != %d\n", tm.tmDescent, tm_orig->tmDescent * scale_y); + ok(near_match(tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x), "ave width %d != %d\n", tm.tmAveCharWidth, tm_orig->tmAveCharWidth * scale_x); + ok(near_match(tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x), "max width %d != %d\n", tm.tmMaxCharWidth, tm_orig->tmMaxCharWidth * scale_x); - ok(lf.lfHeight == lfHeight, "lf %d != %d\n", lf.lfHeight, lfHeight); + ok(lf.lfHeight == lfHeight, "lfHeight %d != %d\n", lf.lfHeight, lfHeight); if (lf.lfHeight) { if (lf.lfWidth) - ok(lf.lfWidth == tm.tmAveCharWidth, "lf %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth); + ok(lf.lfWidth == tm.tmAveCharWidth, "lfWidth %d != tm %d\n", lf.lfWidth, tm.tmAveCharWidth); } else - ok(lf.lfWidth == lfWidth, "lf %d != %d\n", lf.lfWidth, lfWidth); + ok(lf.lfWidth == lfWidth, "lfWidth %d != %d\n", lf.lfWidth, lfWidth); GetTextExtentPoint32A(hdc, test_str, test_str_len, &size); - ok(size.cx == size_orig->cx * scale_x, "%d != %d\n", size.cx, size_orig->cx * scale_x); - ok(size.cy == size_orig->cy * scale_y, "%d != %d\n", size.cy, size_orig->cy * scale_y); + ok(near_match(size.cx, size_orig->cx * scale_x), "cx %d != %d\n", size.cx, size_orig->cx * scale_x); + ok(size.cy == size_orig->cy * scale_y, "cy %d != %d\n", size.cy, size_orig->cy * scale_y); GetCharWidthA(hdc, 'A', 'A', &width_of_A); - ok(width_of_A == width_of_A_orig * scale_x, "%d != %d\n", width_of_A, width_of_A_orig * scale_x); + ok(near_match(width_of_A, width_of_A_orig * scale_x), "width A %d != %d\n", width_of_A, width_of_A_orig * scale_x); SelectObject(hdc, old_hfont); } @@ -286,6 +353,216 @@ static void test_bitmap_font(void) ReleaseDC(0, hdc); } +/* Test how GDI scales outline font metrics */ +static void test_outline_font(void) +{ + static const char test_str[11] = "Test String"; + HDC hdc; + LOGFONTA lf; + HFONT hfont, old_hfont; + OUTLINETEXTMETRICA otm; + SIZE size_orig; + INT width_orig, height_orig, lfWidth; + XFORM xform; + GLYPHMETRICS gm; + MAT2 mat = { {0,1}, {0,0}, {0,0}, {0,1} }; + MAT2 mat2 = { {0x8000,0}, {0,0}, {0,0}, {0x8000,0} }; + POINT pt; + INT ret; + + if (!is_truetype_font_installed("Arial")) + { + skip("Arial is not installed\n"); + return; + } + + hdc = CreateCompatibleDC(0); + + memset(&lf, 0, sizeof(lf)); + strcpy(lf.lfFaceName, "Arial"); + lf.lfHeight = 72; + hfont = create_font("outline", &lf); + old_hfont = SelectObject(hdc, hfont); + otm.otmSize = sizeof(otm); + ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n"); + ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n"); + ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n"); + SelectObject(hdc, old_hfont); + + test_font_metrics(hdc, hfont, lf.lfHeight, otm.otmTextMetrics.tmAveCharWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + DeleteObject(hfont); + + /* font of otmEMSquare height helps to avoid a lot of rounding errors */ + lf.lfHeight = otm.otmEMSquare; + lf.lfHeight = -lf.lfHeight; + hfont = create_font("outline", &lf); + old_hfont = SelectObject(hdc, hfont); + otm.otmSize = sizeof(otm); + ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "GetTextMetricsA failed\n"); + ok(GetTextExtentPoint32A(hdc, test_str, sizeof(test_str), &size_orig), "GetTextExtentPoint32A failed\n"); + ok(GetCharWidthA(hdc, 'A', 'A', &width_orig), "GetCharWidthA failed\n"); + SelectObject(hdc, old_hfont); + DeleteObject(hfont); + + height_orig = otm.otmTextMetrics.tmHeight; + lfWidth = otm.otmTextMetrics.tmAveCharWidth; + + /* test integer scaling 3x2 */ + lf.lfHeight = height_orig * 2; + lf.lfWidth = lfWidth * 3; + hfont = create_font("3x2", &lf); + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 2); + DeleteObject(hfont); + + /* test integer scaling 3x3 */ + lf.lfHeight = height_orig * 3; + lf.lfWidth = lfWidth * 3; + hfont = create_font("3x3", &lf); + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 3, 3); + DeleteObject(hfont); + + /* test integer scaling 1x1 */ + lf.lfHeight = height_orig * 1; + lf.lfWidth = lfWidth * 1; + hfont = create_font("1x1", &lf); + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + DeleteObject(hfont); + + /* test integer scaling 1x1 */ + lf.lfHeight = height_orig; + lf.lfWidth = 0; + hfont = create_font("1x1", &lf); + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + old_hfont = SelectObject(hdc, hfont); + /* with an identity matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + ok(gm.gmCellIncX == width_orig, "incX %d != %d\n", gm.gmCellIncX, width_orig); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + /* with a custom matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + ok(gm.gmCellIncX == width_orig/2, "incX %d != %d\n", gm.gmCellIncX, width_orig/2); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + SelectObject(hdc, old_hfont); + + if (!SetGraphicsMode(hdc, GM_ADVANCED)) + { + DeleteObject(hfont); + DeleteDC(hdc); + skip("GM_ADVANCED is not supported on this platform\n"); + return; + } + + xform.eM11 = 20.0f; + xform.eM12 = 0.0f; + xform.eM21 = 0.0f; + xform.eM22 = 20.0f; + xform.eDx = 0.0f; + xform.eDy = 0.0f; + + SetLastError(0xdeadbeef); + ret = SetWorldTransform(hdc, &xform); + ok(ret, "SetWorldTransform error %u\n", GetLastError()); + + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + old_hfont = SelectObject(hdc, hfont); + /* with an identity matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x); + ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + /* with a custom matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2); + ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + SelectObject(hdc, old_hfont); + + SetLastError(0xdeadbeef); + ret = SetMapMode(hdc, MM_LOMETRIC); + ok(ret == MM_TEXT, "expected MM_TEXT, got %d, error %u\n", ret, GetLastError()); + + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + old_hfont = SelectObject(hdc, hfont); + /* with an identity matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + /* with a custom matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(gm.gmCellIncX == (pt.x + 1)/2, "incX %d != %d\n", gm.gmCellIncX, (pt.x + 1)/2); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + SelectObject(hdc, old_hfont); + + SetLastError(0xdeadbeef); + ret = SetMapMode(hdc, MM_TEXT); + ok(ret == MM_LOMETRIC, "expected MM_LOMETRIC, got %d, error %u\n", ret, GetLastError()); + + test_font_metrics(hdc, hfont, lf.lfHeight, lf.lfWidth, test_str, sizeof(test_str), &otm.otmTextMetrics, &size_orig, width_orig, 1, 1); + + old_hfont = SelectObject(hdc, hfont); + /* with an identity matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(gm.gmCellIncX == pt.x, "incX %d != %d\n", gm.gmCellIncX, pt.x); + ok(gm.gmCellIncX == 20 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 20 * width_orig); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + /* with a custom matrix */ + memset(&gm, 0, sizeof(gm)); + SetLastError(0xdeadbeef); + ret = GetGlyphOutlineA(hdc, 'A', GGO_METRICS, &gm, 0, NULL, &mat2); + ok(ret != GDI_ERROR, "GetGlyphOutlineA error %d\n", GetLastError()); + trace("gm.gmCellIncX %d, width_orig %d\n", gm.gmCellIncX, width_orig); + pt.x = width_orig; pt.y = 0; + LPtoDP(hdc, &pt, 1); + ok(gm.gmCellIncX == pt.x/2, "incX %d != %d\n", gm.gmCellIncX, pt.x/2); + ok(gm.gmCellIncX == 10 * width_orig, "incX %d != %d\n", gm.gmCellIncX, 10 * width_orig); + ok(gm.gmCellIncY == 0, "incY %d != 0\n", gm.gmCellIncY); + SelectObject(hdc, old_hfont); + + DeleteObject(hfont); + DeleteDC(hdc); +} + static INT CALLBACK find_font_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam) { LOGFONT *lf = (LOGFONT *)lParam; @@ -781,6 +1058,8 @@ static void test_GetKerningPairs(void) kd[i].otmDescent, otm.otmDescent); ok(kd[i].otmLineGap == otm.otmLineGap, "expected %u, got %u\n", kd[i].otmLineGap, otm.otmLineGap); + ok(near_match(kd[i].otmMacDescent, otm.otmMacDescent), "expected %d, got %d\n", + kd[i].otmMacDescent, otm.otmMacDescent); todo_wine { ok(kd[i].otmsCapEmHeight == otm.otmsCapEmHeight, "expected %u, got %u\n", kd[i].otmsCapEmHeight, otm.otmsCapEmHeight); @@ -788,8 +1067,6 @@ todo_wine { kd[i].otmsXHeight, otm.otmsXHeight); ok(kd[i].otmMacAscent == otm.otmMacAscent, "expected %d, got %d\n", kd[i].otmMacAscent, otm.otmMacAscent); - ok(kd[i].otmMacDescent == otm.otmMacDescent, "expected %d, got %d\n", - kd[i].otmMacDescent, otm.otmMacDescent); /* FIXME: this one sometimes succeeds due to expected 0, enable it when removing todo */ if (0) ok(kd[i].otmMacLineGap == otm.otmMacLineGap, "expected %u, got %u\n", kd[i].otmMacLineGap, otm.otmMacLineGap); @@ -1097,8 +1374,8 @@ static BOOL get_glyph_indices(INT charset, UINT code_page, WORD *idx, UINT count ok(cs == charset, "expected %d, got %d\n", charset, cs); SetLastError(0xdeadbeef); - ret = GetTextFace(hdc, sizeof(name), name); - ok(ret, "GetTextFace error %u\n", GetLastError()); + ret = GetTextFaceA(hdc, sizeof(name), name); + ok(ret, "GetTextFaceA error %u\n", GetLastError()); if (charset == SYMBOL_CHARSET) { @@ -1771,11 +2048,23 @@ static void test_GetTextMetrics(void) static void test_nonexistent_font(void) { + static const struct + { + const char *name; + int charset; + } font_subst[] = + { + { "Times New Roman Baltic", 186 }, + { "Times New Roman CE", 238 }, + { "Times New Roman CYR", 204 }, + { "Times New Roman Greek", 161 }, + { "Times New Roman TUR", 162 } + }; LOGFONTA lf; HDC hdc; HFONT hfont; CHARSETINFO csi; - INT cs, expected_cs; + INT cs, expected_cs, i; char buf[LF_FACESIZE]; if (!is_truetype_font_installed("Arial") || @@ -1842,22 +2131,6 @@ todo_wine /* Wine uses Arial for all substitutions */ memset(&lf, 0, sizeof(lf)); lf.lfHeight = -13; lf.lfWeight = FW_DONTCARE; - strcpy(lf.lfFaceName, "Times New Roman CE"); - hfont = CreateFontIndirectA(&lf); - hfont = SelectObject(hdc, hfont); - GetTextFaceA(hdc, sizeof(buf), buf); -todo_wine /* Wine uses Arial for all substitutions */ - ok(!lstrcmpiA(buf, "Times New Roman CE") /* XP, Vista */ || - !lstrcmpiA(buf, "MS Serif") /* Win9x */ || - !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */ - "Got %s\n", buf); - cs = GetTextCharset(hdc); - ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs); - DeleteObject(SelectObject(hdc, hfont)); - - memset(&lf, 0, sizeof(lf)); - lf.lfHeight = -13; - lf.lfWeight = FW_DONTCARE; strcpy(lf.lfFaceName, "Times New Roman"); hfont = CreateFontIndirectA(&lf); hfont = SelectObject(hdc, hfont); @@ -1867,18 +2140,46 @@ todo_wine /* Wine uses Arial for all substitutions */ ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs); DeleteObject(SelectObject(hdc, hfont)); - memset(&lf, 0, sizeof(lf)); - lf.lfHeight = -13; - lf.lfWeight = FW_REGULAR; - strcpy(lf.lfFaceName, "Times New Roman CE"); - hfont = CreateFontIndirectA(&lf); - hfont = SelectObject(hdc, hfont); - GetTextFaceA(hdc, sizeof(buf), buf); - ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ || - !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "Got %s\n", buf); - cs = GetTextCharset(hdc); - ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs); - DeleteObject(SelectObject(hdc, hfont)); + for (i = 0; i < sizeof(font_subst)/sizeof(font_subst[0]); i++) + { + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = -13; + lf.lfWeight = FW_REGULAR; + strcpy(lf.lfFaceName, font_subst[i].name); + hfont = CreateFontIndirectA(&lf); + hfont = SelectObject(hdc, hfont); + cs = GetTextCharset(hdc); + if (font_subst[i].charset == expected_cs) + { + ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs); + GetTextFaceA(hdc, sizeof(buf), buf); + ok(!lstrcmpiA(buf, font_subst[i].name), "expected %s, got %s\n", font_subst[i].name, buf); + } + else + { + ok(cs == ANSI_CHARSET, "expected ANSI_CHARSET, got %d\n", cs); + GetTextFaceA(hdc, sizeof(buf), buf); + ok(!lstrcmpiA(buf, "Arial") /* XP, Vista */ || + !lstrcmpiA(buf, "Times New Roman") /* Win9x */, "got %s\n", buf); + } + DeleteObject(SelectObject(hdc, hfont)); + + memset(&lf, 0, sizeof(lf)); + lf.lfHeight = -13; + lf.lfWeight = FW_DONTCARE; + strcpy(lf.lfFaceName, font_subst[i].name); + hfont = CreateFontIndirectA(&lf); + hfont = SelectObject(hdc, hfont); + GetTextFaceA(hdc, sizeof(buf), buf); + ok(!lstrcmpiA(buf, "Arial") /* Wine */ || + !lstrcmpiA(buf, font_subst[i].name) /* XP, Vista */ || + !lstrcmpiA(buf, "MS Serif") /* Win9x */ || + !lstrcmpiA(buf, "MS Sans Serif"), /* win2k3 */ + "got %s\n", buf); + cs = GetTextCharset(hdc); + ok(cs == expected_cs, "expected %d, got %d\n", expected_cs, cs); + DeleteObject(SelectObject(hdc, hfont)); + } ReleaseDC(0, hdc); } @@ -1930,12 +2231,96 @@ static void test_GdiRealizationInfo(void) ReleaseDC(0, hdc); } +/* Tests on XP SP2 show that the ANSI version of GetTextFace does NOT include + the nul in the count of characters copied when the face name buffer is not + NULL, whereas it does if the buffer is NULL. Further, the Unicode version + always includes it. */ +static void test_GetTextFace(void) +{ + static const char faceA[] = "Tahoma"; + static const WCHAR faceW[] = {'T','a','h','o','m','a', 0}; + LOGFONTA fA = {0}; + LOGFONTW fW = {0}; + char bufA[LF_FACESIZE]; + WCHAR bufW[LF_FACESIZE]; + HFONT f, g; + HDC dc; + int n; + + /* 'A' case. */ + memcpy(fA.lfFaceName, faceA, sizeof faceA); + f = CreateFontIndirectA(&fA); + ok(f != NULL, "CreateFontIndirectA failed\n"); + + dc = GetDC(NULL); + g = SelectObject(dc, f); + n = GetTextFaceA(dc, sizeof bufA, bufA); + ok(n == sizeof faceA - 1, "GetTextFaceA returned %d\n", n); + ok(lstrcmpA(faceA, bufA) == 0, "GetTextFaceA\n"); + + /* Play with the count arg. */ + bufA[0] = 'x'; + n = GetTextFaceA(dc, 0, bufA); + ok(n == 0, "GetTextFaceA returned %d\n", n); + ok(bufA[0] == 'x', "GetTextFaceA buf[0] == %d\n", bufA[0]); + + bufA[0] = 'x'; + n = GetTextFaceA(dc, 1, bufA); + ok(n == 0, "GetTextFaceA returned %d\n", n); + ok(bufA[0] == '\0', "GetTextFaceA buf[0] == %d\n", bufA[0]); + + bufA[0] = 'x'; bufA[1] = 'y'; + n = GetTextFaceA(dc, 2, bufA); + ok(n == 1, "GetTextFaceA returned %d\n", n); + ok(bufA[0] == faceA[0] && bufA[1] == '\0', "GetTextFaceA didn't copy\n"); + + n = GetTextFaceA(dc, 0, NULL); + ok(n == sizeof faceA, "GetTextFaceA returned %d\n", n); + + DeleteObject(SelectObject(dc, g)); + ReleaseDC(NULL, dc); + + /* 'W' case. */ + memcpy(fW.lfFaceName, faceW, sizeof faceW); + f = CreateFontIndirectW(&fW); + ok(f != NULL, "CreateFontIndirectW failed\n"); + + dc = GetDC(NULL); + g = SelectObject(dc, f); + n = GetTextFaceW(dc, sizeof bufW / sizeof bufW[0], bufW); + ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n); + ok(lstrcmpW(faceW, bufW) == 0, "GetTextFaceW\n"); + + /* Play with the count arg. */ + bufW[0] = 'x'; + n = GetTextFaceW(dc, 0, bufW); + ok(n == 0, "GetTextFaceW returned %d\n", n); + ok(bufW[0] == 'x', "GetTextFaceW buf[0] == %d\n", bufW[0]); + + bufW[0] = 'x'; + n = GetTextFaceW(dc, 1, bufW); + ok(n == 1, "GetTextFaceW returned %d\n", n); + ok(bufW[0] == '\0', "GetTextFaceW buf[0] == %d\n", bufW[0]); + + bufW[0] = 'x'; bufW[1] = 'y'; + n = GetTextFaceW(dc, 2, bufW); + ok(n == 2, "GetTextFaceW returned %d\n", n); + ok(bufW[0] == faceW[0] && bufW[1] == '\0', "GetTextFaceW didn't copy\n"); + + n = GetTextFaceW(dc, 0, NULL); + ok(n == sizeof faceW / sizeof faceW[0], "GetTextFaceW returned %d\n", n); + + DeleteObject(SelectObject(dc, g)); + ReleaseDC(NULL, dc); +} + START_TEST(font) { init(); test_logfont(); test_bitmap_font(); + test_outline_font(); test_bitmap_font_metrics(); test_GdiGetCharDimensions(); test_GetCharABCWidths(); @@ -1964,4 +2349,5 @@ START_TEST(font) skip("Arial Black or Symbol/Wingdings is not installed\n"); test_GetTextMetrics(); test_GdiRealizationInfo(); + test_GetTextFace(); } diff --git a/dlls/gdiplus/font.c b/dlls/gdiplus/font.c index 82523cea4c6..86a32231cc7 100644 --- a/dlls/gdiplus/font.c +++ b/dlls/gdiplus/font.c @@ -22,12 +22,140 @@ #include "winbase.h" #include "wingdi.h" #include "winnls.h" +#include "winreg.h" +#include "wine/debug.h" +#include "wine/unicode.h" + +WINE_DEFAULT_DEBUG_CHANNEL (gdiplus); #include "objbase.h" #include "gdiplus.h" #include "gdiplus_private.h" +static const REAL mm_per_pixel = 25.4; + +static inline REAL get_dpi (void) +{ + REAL dpi; + GpGraphics *graphics; + HDC hdc = GetDC(0); + GdipCreateFromHDC (hdc, &graphics); + GdipGetDpiX(graphics, &dpi); + GdipDeleteGraphics(graphics); + ReleaseDC (0, hdc); + + return dpi; +} + +static inline REAL point_to_pixel (REAL point) +{ + return point * 1.5; +} + +static inline REAL inch_to_pixel (REAL inch) +{ + return inch * get_dpi(); +} + +static inline REAL document_to_pixel (REAL doc) +{ + return doc * (get_dpi() / 300.0); /* Per MSDN */ +} + +static inline REAL mm_to_pixel (REAL mm) +{ + return mm * (get_dpi() / mm_per_pixel); +} + +/******************************************************************************* + * GdipCreateFont [GDIPLUS.@] + * + * Create a new font based off of a FontFamily + * + * PARAMS + * *fontFamily [I] Family to base the font off of + * emSize [I] Size of the font + * style [I] Bitwise OR of FontStyle enumeration + * unit [I] Unit emSize is measured in + * **font [I] the resulting Font object + * + * RETURNS + * SUCCESS: Ok + * FAILURE: InvalidParameter if fontfamily or font is NULL. + * FAILURE: FontFamilyNotFound if an invalid FontFamily is given + * + * NOTES + * UnitDisplay is unsupported. + * emSize is stored separately from lfHeight, to hold the fraction. + */ +GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily, + REAL emSize, INT style, Unit unit, GpFont **font) +{ + WCHAR facename[LF_FACESIZE]; + LOGFONTW* lfw; + const TEXTMETRICW* tmw; + GpStatus stat; + + if ((!fontFamily && fontFamily->FamilyName && font)) + return InvalidParameter; + + TRACE("%p (%s), %f, %d, %d, %p\n", fontFamily, + debugstr_w(fontFamily->FamilyName), emSize, style, unit, font); + + stat = GdipGetFamilyName (fontFamily, facename, 0); + if (stat != Ok) return stat; + *font = GdipAlloc(sizeof(GpFont)); + + tmw = &fontFamily->tmw; + lfw = &((*font)->lfw); + ZeroMemory(&(*lfw), sizeof(*lfw)); + + lfw->lfWeight = tmw->tmWeight; + lfw->lfItalic = tmw->tmItalic; + lfw->lfUnderline = tmw->tmUnderlined; + lfw->lfStrikeOut = tmw->tmStruckOut; + lfw->lfCharSet = tmw->tmCharSet; + lfw->lfPitchAndFamily = tmw->tmPitchAndFamily; + lstrcpynW((lfw->lfFaceName), facename, sizeof(WCHAR) * LF_FACESIZE); + + switch (unit) + { + case UnitWorld: + /* FIXME: Figure out when World != Pixel */ + lfw->lfHeight = emSize; break; + case UnitDisplay: + FIXME("Unknown behavior for UnitDisplay! Please report!\n"); + /* FIXME: Figure out how this works... + * MSDN says that if "DISPLAY" is a monitor, then pixel should be + * used. That's not what I got. Tests on Windows revealed no output, + * and the tests in tests/font crash windows */ + lfw->lfHeight = 0; break; + case UnitPixel: + lfw->lfHeight = emSize; break; + case UnitPoint: + lfw->lfHeight = point_to_pixel(emSize); break; + case UnitInch: + lfw->lfHeight = inch_to_pixel(emSize); break; + case UnitDocument: + lfw->lfHeight = document_to_pixel(emSize); break; + case UnitMillimeter: + lfw->lfHeight = mm_to_pixel(emSize); break; + } + + lfw->lfHeight *= -1; + + lfw->lfWeight = style & FontStyleBold ? 700 : 400; + lfw->lfItalic = style & FontStyleItalic; + lfw->lfUnderline = style & FontStyleUnderline; + lfw->lfStrikeOut = style & FontStyleStrikeout; + + (*font)->unit = unit; + (*font)->emSize = emSize; + + return Ok; +} + GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc, GDIPCONST LOGFONTW *logfont, GpFont **font) { @@ -47,6 +175,9 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc, (*font)->lfw.lfUnderline = logfont->lfUnderline; (*font)->lfw.lfStrikeOut = logfont->lfStrikeOut; + (*font)->emSize = logfont->lfHeight; + (*font)->unit = UnitPixel; + hfont = CreateFontIndirectW(&(*font)->lfw); oldfont = SelectObject(hdc, hfont); GetTextMetricsW(hdc, &textmet); @@ -106,6 +237,51 @@ GpStatus WINGDIPAPI GdipCreateFontFromDC(HDC hdc, GpFont **font) return GdipCreateFontFromLogfontW(hdc, &lfw, font); } +/****************************************************************************** + * GdipGetFontSize [GDIPLUS.@] + * + * Returns the size of the font in Units + * + * PARAMS + * *font [I] The font to retrieve size from + * *size [O] Pointer to hold retrieved value + * + * RETURNS + * SUCCESS: Ok + * FAILURE: InvalidParamter (font or size was NULL) + * + * NOTES + * Size returned is actually emSize -- not internal size used for drawing. + */ +GpStatus WINGDIPAPI GdipGetFontSize(GpFont *font, REAL *size) +{ + if (!(font && size)) return InvalidParameter; + + *size = font->emSize; + + return Ok; +} + +/******************************************************************************* + * GdipGetFontUnit [GDIPLUS.@] + * + * PARAMS + * font [I] Font to retrieve from + * unit [O] Return value + * + * RETURNS + * FAILURE: font or unit was NULL + * OK: otherwise + */ +GpStatus WINGDIPAPI GdipGetFontUnit(GpFont *font, Unit *unit) +{ + if (!(font && unit)) return InvalidParameter; + + *unit = font->unit; + + return Ok; +} + /* FIXME: use graphics */ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, LOGFONTW *lfw) @@ -130,3 +306,211 @@ GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont) return Ok; } + +/* Borrowed from GDI32 */ +static INT CALLBACK is_font_installed_proc(const LOGFONTW *elf, + const TEXTMETRICW *ntm, DWORD type, LPARAM lParam) +{ + return 0; +} + +static BOOL is_font_installed(const WCHAR *name) +{ + HDC hdc = GetDC(0); + BOOL ret = FALSE; + + if(!EnumFontFamiliesW(hdc, name, is_font_installed_proc, 0)) + ret = TRUE; + + ReleaseDC(0, hdc); + return ret; +} + +/******************************************************************************* + * GdipCreateFontFamilyFromName [GDIPLUS.@] + * + * Creates a font family object based on a supplied name + * + * PARAMS + * name [I] Name of the font + * fontCollection [I] What font collection (if any) the font belongs to (may be NULL) + * FontFamily [O] Pointer to the resulting FontFamily object + * + * RETURNS + * SUCCESS: Ok + * FAILURE: FamilyNotFound if the requested FontFamily does not exist on the system + * FAILURE: Invalid parameter if FontFamily or name is NULL + * + * NOTES + * If fontCollection is NULL then the object is not part of any collection + * + */ + +GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name, + GpFontCollection *fontCollection, + GpFontFamily **FontFamily) +{ + GpFontFamily* ffamily; + HDC hdc; + HFONT hFont, hfont_old; + LOGFONTW lfw; + + TRACE("%s, %p %p\n", debugstr_w(name), fontCollection, FontFamily); + + if (!(name && FontFamily)) + return InvalidParameter; + if (fontCollection) + FIXME("No support for FontCollections yet!\n"); + if (!is_font_installed(name)) + return FontFamilyNotFound; + + ffamily = GdipAlloc(sizeof (GpFontFamily)); + if (!ffamily) return OutOfMemory; + + hdc = GetDC(0); + lstrcpynW(lfw.lfFaceName, name, sizeof(WCHAR) * LF_FACESIZE); + hFont = CreateFontIndirectW (&lfw); + hfont_old = SelectObject(hdc, hFont); + + GetTextMetricsW(hdc, &ffamily->tmw); + DeleteObject(SelectObject(hdc, hfont_old)); + + ffamily->FamilyName = GdipAlloc(LF_FACESIZE * sizeof (WCHAR)); + if (!ffamily->FamilyName) + { + GdipFree(ffamily); + ReleaseDC(0, hdc); + return OutOfMemory; + } + + lstrcpynW(ffamily->FamilyName, name, sizeof(WCHAR) * LF_FACESIZE); + + *FontFamily = ffamily; + ReleaseDC(0, hdc); + + return Ok; +} + +/******************************************************************************* + * GdipGetFamilyName [GDIPLUS.@] + * + * Returns the family name into name + * + * PARAMS + * *family [I] Family to retrieve from + * *name [O] WCHARS of the family name + * LANGID [I] charset + * + * RETURNS + * SUCCESS: Ok + * FAILURE: InvalidParameter if family is NULL + * + * NOTES + * If name is a NULL ptr, then both XP and Vista will crash (so we do as well) + */ +GpStatus WINGDIPAPI GdipGetFamilyName (GDIPCONST GpFontFamily *family, + WCHAR *name, LANGID language) +{ + if (family == NULL) + return InvalidParameter; + + TRACE("%p, %p, %d\n", family, name, language); + + if (language != LANG_NEUTRAL) + FIXME("No support for handling of multiple languages!\n"); + + lstrcpynW (name, family->FamilyName, LF_FACESIZE); + + return Ok; +} + + +/***************************************************************************** + * GdipDeleteFontFamily [GDIPLUS.@] + * + * Removes the specified FontFamily + * + * PARAMS + * *FontFamily [I] The family to delete + * + * RETURNS + * SUCCESS: Ok + * FAILURE: InvalidParameter if FontFamily is NULL. + * + */ +GpStatus WINGDIPAPI GdipDeleteFontFamily(GpFontFamily *FontFamily) +{ + if (!FontFamily) + return InvalidParameter; + TRACE("Deleting %p (%s)\n", FontFamily, debugstr_w(FontFamily->FamilyName)); + + if (FontFamily->FamilyName) GdipFree (FontFamily->FamilyName); + GdipFree (FontFamily); + + return Ok; +} + +/***************************************************************************** + * GdipGetGenericFontFamilyMonospace [GDIPLUS.@] + * + * Obtains a serif family (Courier New on Windows) + * + * PARAMS + * **nativeFamily [I] Where the font will be stored + * + * RETURNS + * InvalidParameter if nativeFamily is NULL. + * Ok otherwise. + */ +GpStatus WINGDIPAPI GdipGetGenericFontFamilyMonospace(GpFontFamily **nativeFamily) +{ + static const WCHAR CourierNew[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'}; + + if (nativeFamily == NULL) return InvalidParameter; + + return GdipCreateFontFamilyFromName(CourierNew, NULL, nativeFamily); +} + +/***************************************************************************** + * GdipGetGenericFontFamilySerif [GDIPLUS.@] + * + * Obtains a serif family (Times New Roman on Windows) + * + * PARAMS + * **nativeFamily [I] Where the font will be stored + * + * RETURNS + * InvalidParameter if nativeFamily is NULL. + * Ok otherwise. + */ +GpStatus WINGDIPAPI GdipGetGenericFontFamilySerif(GpFontFamily **nativeFamily) +{ + static const WCHAR TimesNewRoman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'}; + + if (nativeFamily == NULL) return InvalidParameter; + + return GdipCreateFontFamilyFromName(TimesNewRoman, NULL, nativeFamily); +} + +/***************************************************************************** + * GdipGetGenericFontFamilySansSerif [GDIPLUS.@] + * + * Obtains a serif family (Microsoft Sans Serif on Windows) + * + * PARAMS + * **nativeFamily [I] Where the font will be stored + * + * RETURNS + * InvalidParameter if nativeFamily is NULL. + * Ok otherwise. + */ +GpStatus WINGDIPAPI GdipGetGenericFontFamilySansSerif(GpFontFamily **nativeFamily) +{ + /* FIXME: On Windows this is called Microsoft Sans Serif, this shouldn't + * affect anything */ + static const WCHAR MSSansSerif[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}; + + if (nativeFamily == NULL) return InvalidParameter; + + return GdipCreateFontFamilyFromName(MSSansSerif, NULL, nativeFamily); +} diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec index 23346fc02bf..7e127d7be19 100644 --- a/dlls/gdiplus/gdiplus.spec +++ b/dlls/gdiplus/gdiplus.spec @@ -23,8 +23,8 @@ @ stdcall GdipAddPathPath(ptr ptr long) @ stub GdipAddPathPie @ stub GdipAddPathPieI -@ stub GdipAddPathPolygon -@ stub GdipAddPathPolygonI +@ stdcall GdipAddPathPolygon(ptr ptr long) +@ stdcall GdipAddPathPolygonI(ptr ptr long) @ stdcall GdipAddPathRectangle(ptr long long long long) @ stdcall GdipAddPathRectangleI(ptr long long long long) @ stdcall GdipAddPathRectangles(ptr ptr long) @@ -45,7 +45,7 @@ @ stub GdipBitmapSetPixel @ stub GdipBitmapSetResolution @ stdcall GdipBitmapUnlockBits(ptr ptr) -@ stub GdipClearPathMarkers +@ stdcall GdipClearPathMarkers(ptr) @ stub GdipCloneBitmapArea @ stub GdipCloneBitmapAreaI @ stdcall GdipCloneBrush(ptr ptr) @@ -53,7 +53,7 @@ @ stdcall GdipCloneFont(ptr ptr) @ stub GdipCloneFontFamily @ stub GdipCloneImage -@ stub GdipCloneImageAttributes +@ stdcall GdipCloneImageAttributes(ptr ptr) @ stdcall GdipCloneMatrix(ptr ptr) @ stdcall GdipClonePath(ptr ptr) @ stdcall GdipClonePen(ptr ptr) @@ -84,8 +84,8 @@ @ stub GdipCreateCachedBitmap @ stdcall GdipCreateCustomLineCap(ptr ptr long long ptr) @ stub GdipCreateEffect -@ stub GdipCreateFont -@ stub GdipCreateFontFamilyFromName +@ stdcall GdipCreateFont(ptr long long long ptr) +@ stdcall GdipCreateFontFamilyFromName(wstr ptr ptr) @ stdcall GdipCreateFontFromDC(long ptr) @ stdcall GdipCreateFontFromLogfontA(long ptr ptr) @ stdcall GdipCreateFontFromLogfontW(long ptr ptr) @@ -141,7 +141,7 @@ @ stdcall GdipDeleteCustomLineCap(ptr) @ stub GdipDeleteEffect @ stdcall GdipDeleteFont(ptr) -@ stub GdipDeleteFontFamily +@ stdcall GdipDeleteFontFamily(ptr) @ stdcall GdipDeleteGraphics(ptr) @ stdcall GdipDeleteMatrix(ptr) @ stdcall GdipDeletePath(ptr) @@ -170,8 +170,8 @@ @ stdcall GdipDrawCurve(ptr ptr ptr long) @ stdcall GdipDrawCurveI(ptr ptr ptr long) @ stub GdipDrawDriverString -@ stub GdipDrawEllipse -@ stub GdipDrawEllipseI +@ stdcall GdipDrawEllipse(ptr ptr long long long long) +@ stdcall GdipDrawEllipseI(ptr ptr long long long long) @ stdcall GdipDrawImage(ptr ptr long long) @ stub GdipDrawImageFX @ stdcall GdipDrawImageI(ptr ptr long long) @@ -264,17 +264,17 @@ @ stub GdipGetEncoderParameterList @ stub GdipGetEncoderParameterListSize @ stub GdipGetFamily -@ stub GdipGetFamilyName +@ stdcall GdipGetFamilyName(ptr ptr long) @ stub GdipGetFontCollectionFamilyCount @ stub GdipGetFontCollectionFamilyList @ stub GdipGetFontHeight @ stub GdipGetFontHeightGivenDPI -@ stub GdipGetFontSize +@ stdcall GdipGetFontSize(ptr ptr) @ stub GdipGetFontStyle -@ stub GdipGetFontUnit -@ stub GdipGetGenericFontFamilyMonospace -@ stub GdipGetGenericFontFamilySansSerif -@ stub GdipGetGenericFontFamilySerif +@ stdcall GdipGetFontUnit(ptr ptr) +@ stdcall GdipGetGenericFontFamilyMonospace(ptr) +@ stdcall GdipGetGenericFontFamilySansSerif(ptr) +@ stdcall GdipGetGenericFontFamilySerif(ptr) @ stub GdipGetHatchBackgroundColor @ stub GdipGetHatchForegroundColor @ stub GdipGetHatchStyle @@ -355,19 +355,19 @@ @ stub GdipGetPenCustomEndCap @ stub GdipGetPenCustomStartCap @ stdcall GdipGetPenDashArray(ptr ptr long) -@ stub GdipGetPenDashCap197819 +@ stdcall GdipGetPenDashCap197819(ptr ptr) @ stub GdipGetPenDashCount @ stdcall GdipGetPenDashOffset(ptr ptr) @ stdcall GdipGetPenDashStyle(ptr ptr) -@ stub GdipGetPenEndCap +@ stdcall GdipGetPenEndCap(ptr ptr) @ stub GdipGetPenFillType -@ stub GdipGetPenLineJoin -@ stub GdipGetPenMiterLimit +@ stdcall GdipGetPenLineJoin(ptr ptr) +@ stdcall GdipGetPenMiterLimit(ptr ptr) @ stub GdipGetPenMode -@ stub GdipGetPenStartCap +@ stdcall GdipGetPenStartCap(ptr ptr) @ stub GdipGetPenTransform -@ stub GdipGetPenUnit -@ stub GdipGetPenWidth +@ stdcall GdipGetPenUnit(ptr ptr) +@ stdcall GdipGetPenWidth(ptr ptr) @ stdcall GdipGetPixelOffsetMode(ptr ptr) @ stdcall GdipGetPointCount(ptr ptr) @ stub GdipGetPropertyCount @@ -407,7 +407,7 @@ @ stub GdipGraphicsSetAbort @ stub GdipImageForceValidation @ stdcall GdipImageGetFrameCount(ptr ptr ptr) -@ stub GdipImageGetFrameDimensionsCount +@ stdcall GdipImageGetFrameDimensionsCount(ptr ptr) @ stdcall GdipImageGetFrameDimensionsList(ptr ptr long) @ stub GdipImageRotateFlip @ stdcall GdipImageSelectActiveFrame(ptr ptr long) @@ -452,7 +452,7 @@ @ stub GdipNewPrivateFontCollection @ stdcall GdipPathIterCopyData(ptr ptr ptr ptr long long) @ stub GdipPathIterEnumerate -@ stub GdipPathIterGetCount +@ stdcall GdipPathIterGetCount(ptr ptr) @ stub GdipPathIterGetSubpathCount @ stub GdipPathIterHasCurve @ stub GdipPathIterIsValid @@ -561,7 +561,7 @@ @ stdcall GdipSetPathGradientSurroundColorsWithCount(ptr ptr ptr) @ stub GdipSetPathGradientTransform @ stdcall GdipSetPathGradientWrapMode(ptr long) -@ stub GdipSetPathMarker +@ stdcall GdipSetPathMarker(ptr) @ stdcall GdipSetPenBrushFill(ptr ptr) @ stdcall GdipSetPenColor(ptr long) @ stub GdipSetPenCompoundArray diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 539254b5714..b8269f21107 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -174,6 +174,8 @@ struct GpImageAttributes{ struct GpFont{ LOGFONTW lfw; + REAL emSize; + Unit unit; }; struct GpStringFormat{ @@ -185,4 +187,13 @@ struct GpStringFormat{ StringAlignment vertalign; }; +struct GpFontCollection{ + GpFontFamily* FontFamilies; +}; + +struct GpFontFamily{ + TEXTMETRICW tmw; + WCHAR* FamilyName; +}; + #endif diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 5716341affc..c274b2e00fb 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -1106,6 +1106,40 @@ GpStatus WINGDIPAPI GdipDrawCurve2I(GpGraphics *graphics, GpPen *pen, return ret; } +GpStatus WINGDIPAPI GdipDrawEllipse(GpGraphics *graphics, GpPen *pen, REAL x, + REAL y, REAL width, REAL height) +{ + INT save_state; + GpPointF ptf[2]; + POINT pti[2]; + + if(!graphics || !pen) + return InvalidParameter; + + ptf[0].X = x; + ptf[0].Y = y; + ptf[1].X = x + width; + ptf[1].Y = y + height; + + save_state = prepare_dc(graphics, pen); + SelectObject(graphics->hdc, GetStockObject(NULL_BRUSH)); + + transform_and_round_points(graphics, pti, ptf, 2); + + Ellipse(graphics->hdc, pti[0].x, pti[0].y, pti[1].x, pti[1].y); + + restore_dc(graphics, save_state); + + return Ok; +} + +GpStatus WINGDIPAPI GdipDrawEllipseI(GpGraphics *graphics, GpPen *pen, INT x, + INT y, INT width, INT height) +{ + return GdipDrawEllipse(graphics,pen,(REAL)x,(REAL)y,(REAL)width,(REAL)height); +} + + GpStatus WINGDIPAPI GdipDrawImage(GpGraphics *graphics, GpImage *image, REAL x, REAL y) { /* IPicture::Render uses LONG coords */ diff --git a/dlls/gdiplus/graphicspath.c b/dlls/gdiplus/graphicspath.c index 24f25e1ebf2..1da6866647f 100644 --- a/dlls/gdiplus/graphicspath.c +++ b/dlls/gdiplus/graphicspath.c @@ -346,6 +346,55 @@ GpStatus WINGDIPAPI GdipAddPathPath(GpPath *path, GDIPCONST GpPath* addingPath, return Ok; } +GpStatus WINGDIPAPI GdipAddPathPolygon(GpPath *path, GDIPCONST GpPointF *points, INT count) +{ + INT old_count; + + if(!path || !points || count < 3) + return InvalidParameter; + + if(!lengthen_path(path, count)) + return OutOfMemory; + + old_count = path->pathdata.Count; + + memcpy(&path->pathdata.Points[old_count], points, count*sizeof(GpPointF)); + memset(&path->pathdata.Types[old_count + 1], PathPointTypeLine, count - 1); + + /* A polygon is an intrinsic figure */ + path->pathdata.Types[old_count] = PathPointTypeStart; + path->pathdata.Types[old_count + count - 1] |= PathPointTypeCloseSubpath; + path->newfigure = TRUE; + path->pathdata.Count += count; + + return Ok; +} + +GpStatus WINGDIPAPI GdipAddPathPolygonI(GpPath *path, GDIPCONST GpPoint *points, INT count) +{ + GpPointF *ptf; + GpStatus status; + INT i; + + if(!points || count < 3) + return InvalidParameter; + + ptf = GdipAlloc(sizeof(GpPointF) * count); + if(!ptf) + return OutOfMemory; + + for(i = 0; i < count; i++){ + ptf[i].X = (REAL)points[i].X; + ptf[i].Y = (REAL)points[i].Y; + } + + status = GdipAddPathPolygon(path, ptf, count); + + GdipFree(ptf); + + return status; +} + GpStatus WINGDIPAPI GdipClonePath(GpPath* path, GpPath **clone) { if(!path || !clone) @@ -484,17 +533,8 @@ GpStatus WINGDIPAPI GdipGetPathData(GpPath *path, GpPathData* pathData) if(!path || !pathData) return InvalidParameter; - pathData->Count = path->pathdata.Count; - - pathData->Points = GdipAlloc(sizeof(PointF) * pathData->Count); - if(!pathData->Points) - return OutOfMemory; - - pathData->Types = GdipAlloc(pathData->Count); - if(!pathData->Points) - return OutOfMemory; - - /* copy data */ + /* Only copy data. pathData allocation/freeing controlled by wrapper class. + Assumed that pathData is enough wide to get all data - controlled by wrapper too. */ memcpy(pathData->Points, path->pathdata.Points, sizeof(PointF) * pathData->Count); memcpy(pathData->Types , path->pathdata.Types , pathData->Count); @@ -842,3 +882,36 @@ GpStatus WINGDIPAPI GdipAddPathRectanglesI(GpPath *path, GDIPCONST GpRect *rects return retstat; } + +GpStatus WINGDIPAPI GdipSetPathMarker(GpPath* path) +{ + INT count; + + if(!path) + return InvalidParameter; + + count = path->pathdata.Count; + + /* set marker flag */ + if(count > 0) + path->pathdata.Types[count-1] |= PathPointTypePathMarker; + + return Ok; +} + +GpStatus WINGDIPAPI GdipClearPathMarkers(GpPath* path) +{ + INT count; + INT i; + + if(!path) + return InvalidParameter; + + count = path->pathdata.Count; + + for(i = 0; i < count - 1; i++){ + path->pathdata.Types[i] &= ~PathPointTypePathMarker; + } + + return Ok; +} diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index f6dffcfad80..330e54bfb03 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -688,6 +688,19 @@ GpStatus WINGDIPAPI GdipImageGetFrameCount(GpImage *image, return NotImplemented; } +GpStatus WINGDIPAPI GdipImageGetFrameDimensionsCount(GpImage *image, + UINT* count) +{ + if(!image || !count) + return InvalidParameter; + + *count = 1; + + FIXME("stub\n"); + + return Ok; +} + GpStatus WINGDIPAPI GdipImageGetFrameDimensionsList(GpImage* image, GUID* dimensionIDs, UINT count) { diff --git a/dlls/gdiplus/imageattributes.c b/dlls/gdiplus/imageattributes.c index 858ea15e8cd..dcee68b0cd2 100644 --- a/dlls/gdiplus/imageattributes.c +++ b/dlls/gdiplus/imageattributes.c @@ -27,6 +27,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdiplus); +GpStatus WINGDIPAPI GdipCloneImageAttributes(GDIPCONST GpImageAttributes *imageattr, + GpImageAttributes **cloneImageattr) +{ + if(!imageattr || !cloneImageattr) + return InvalidParameter; + + **cloneImageattr = *imageattr; + + return Ok; +} + GpStatus WINGDIPAPI GdipCreateImageAttributes(GpImageAttributes **imageattr) { if(!imageattr) diff --git a/dlls/gdiplus/pathiterator.c b/dlls/gdiplus/pathiterator.c index d1e4e88bf97..67d83a434bb 100644 --- a/dlls/gdiplus/pathiterator.c +++ b/dlls/gdiplus/pathiterator.c @@ -131,3 +131,13 @@ GpStatus WINGDIPAPI GdipPathIterRewind(GpPathIterator *iterator) return Ok; } + +GpStatus WINGDIPAPI GdipPathIterGetCount(GpPathIterator* iterator, INT* count) +{ + if(!iterator || !count) + return InvalidParameter; + + *count = iterator->pathdata.Count; + + return Ok; +} diff --git a/dlls/gdiplus/pen.c b/dlls/gdiplus/pen.c index f6214f1bcb0..852494f2ac2 100644 --- a/dlls/gdiplus/pen.c +++ b/dlls/gdiplus/pen.c @@ -177,6 +177,16 @@ GpStatus WINGDIPAPI GdipGetPenDashArray(GpPen *pen, REAL *dash, INT count) return Ok; } +GpStatus WINGDIPAPI GdipGetPenDashCap197819(GpPen *pen, GpDashCap *dashCap) +{ + if(!pen || !dashCap) + return InvalidParameter; + + *dashCap = pen->dashcap; + + return Ok; +} + GpStatus WINGDIPAPI GdipGetPenDashOffset(GpPen *pen, REAL *offset) { if(!pen || !offset) @@ -197,6 +207,66 @@ GpStatus WINGDIPAPI GdipGetPenDashStyle(GpPen *pen, GpDashStyle *dash) return Ok; } +GpStatus WINGDIPAPI GdipGetPenEndCap(GpPen *pen, GpLineCap *endCap) +{ + if(!pen || !endCap) + return InvalidParameter; + + *endCap = pen->endcap; + + return Ok; +} + +GpStatus WINGDIPAPI GdipGetPenLineJoin(GpPen *pen, GpLineJoin *lineJoin) +{ + if(!pen || !lineJoin) + return InvalidParameter; + + *lineJoin = pen->join; + + return Ok; +} + +GpStatus WINGDIPAPI GdipGetPenMiterLimit(GpPen *pen, REAL *miterLimit) +{ + if(!pen || !miterLimit) + return InvalidParameter; + + *miterLimit = pen->miterlimit; + + return Ok; +} + +GpStatus WINGDIPAPI GdipGetPenStartCap(GpPen *pen, GpLineCap *startCap) +{ + if(!pen || !startCap) + return InvalidParameter; + + *startCap = pen->startcap; + + return Ok; +} + +GpStatus WINGDIPAPI GdipGetPenUnit(GpPen *pen, GpUnit *unit) +{ + if(!pen || !unit) + return InvalidParameter; + + *unit = pen->unit; + + return Ok; +} + +GpStatus WINGDIPAPI GdipGetPenWidth(GpPen *pen, REAL *width) +{ + if(!pen || !width) + return InvalidParameter; + + *width = pen->width; + + return Ok; +} + GpStatus WINGDIPAPI GdipSetPenBrushFill(GpPen *pen, GpBrush *brush) { if(!pen || !brush) diff --git a/dlls/gdiplus/tests/font.c b/dlls/gdiplus/tests/font.c index 71e6f9a7bf2..93efbc4eb45 100644 --- a/dlls/gdiplus/tests/font.c +++ b/dlls/gdiplus/tests/font.c @@ -24,7 +24,59 @@ #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) -static WCHAR arial[] = {'A','r','i','a','l','\0'}; +static const WCHAR arial[] = {'A','r','i','a','l','\0'}; +static const WCHAR nonexistant[] = {'T','h','i','s','F','o','n','t','s','h','o','u','l','d','N','o','t','E','x','i','s','t','\0'}; +static const WCHAR MSSansSerif[] = {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}; +static const WCHAR MicrosoftSansSerif[] = {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f','\0'}; +static const WCHAR TimesNewRoman[] = {'T','i','m','e','s',' ','N','e','w',' ','R','o','m','a','n','\0'}; +static const WCHAR CourierNew[] = {'C','o','u','r','i','e','r',' ','N','e','w','\0'}; + +static const char *debugstr_w(LPCWSTR str) +{ + static char buf[1024]; + WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL); + return buf; +} + + +static void test_createfont(void) +{ + GpFontFamily* fontfamily = NULL; + GpFont* font = NULL; + GpStatus stat; + Unit unit; + UINT i; + REAL size; + + stat = GdipCreateFontFamilyFromName(nonexistant, NULL, &fontfamily); + expect (FontFamilyNotFound, stat); + stat = GdipDeleteFont(font); + expect (InvalidParameter, stat); + stat = GdipCreateFontFamilyFromName(arial, NULL, &fontfamily); + expect (Ok, stat); + stat = GdipCreateFont(fontfamily, 12, FontStyleRegular, UnitPoint, &font); + expect (Ok, stat); + stat = GdipGetFontUnit (font, &unit); + expect (Ok, stat); + expect (UnitPoint, unit); + + /* Test to see if returned size is based on unit (its not) */ + GdipGetFontSize(font, &size); + ok (size == 12, "Expected 12, got %f\n", size); + GdipDeleteFont(font); + + /* Make sure everything is converted correctly for all Units */ + for (i = UnitWorld; i <=UnitMillimeter; i++) + { + if (i == UnitDisplay) continue; /* Crashes WindowsXP, wtf? */ + GdipCreateFont(fontfamily, 24, FontStyleRegular, i, &font); + GdipGetFontSize (font, &size); + ok (size == 24, "Expected 24, got %f (with unit: %d)\n", size, i); + GdipGetFontUnit (font, &unit); + expect (i, unit); + GdipDeleteFont(font); + } +} static void test_logfont(void) { @@ -94,6 +146,95 @@ static void test_logfont(void) ReleaseDC(0, hdc); } +static void test_fontfamily (void) +{ + GpFontFamily** family = NULL; + WCHAR itsName[LF_FACESIZE]; + GpStatus stat; + + /* FontFamily can not be NULL */ + stat = GdipCreateFontFamilyFromName (arial , NULL, family); + expect (InvalidParameter, stat); + + family = GdipAlloc (sizeof (GpFontFamily*)); + + /* FontFamily must be able to actually find the family. + * If it can't, any subsequent calls should fail + * + * We currently fail (meaning we don't) because we don't actually + * test to see if we can successfully get a family + */ + stat = GdipCreateFontFamilyFromName (nonexistant, NULL, family); + expect (FontFamilyNotFound, stat); + stat = GdipGetFamilyName (*family,itsName, LANG_NEUTRAL); + expect (InvalidParameter, stat); + ok ((lstrcmpiW(itsName,nonexistant) != 0), + "Expected a non-zero value for nonexistant font!\n"); + stat = GdipDeleteFontFamily(*family); + expect (InvalidParameter, stat); + + stat = GdipCreateFontFamilyFromName (arial, NULL, family); + expect (Ok, stat); + + stat = GdipGetFamilyName (*family, itsName, LANG_NEUTRAL); + expect (Ok, stat); + expect (0, lstrcmpiW(itsName,arial)); + + if (0) + { + /* Crashes on Windows XP SP2, Vista, and so Wine as well */ + stat = GdipGetFamilyName (*family, NULL, LANG_NEUTRAL); + expect (Ok, stat); + } + + stat = GdipDeleteFontFamily(*family); + expect (Ok, stat); + + if (family) GdipFree (family); +} + + +static void test_getgenerics (void) +{ + GpStatus stat; + GpFontFamily** family; + WCHAR familyName[LF_FACESIZE]; + ZeroMemory(familyName, sizeof(familyName)/sizeof(WCHAR)); + + family = GdipAlloc (sizeof (GpFontFamily*)); + + stat = GdipGetGenericFontFamilySansSerif (family); + expect (Ok, stat); + stat = GdipGetFamilyName (*family, familyName, LANG_NEUTRAL); + expect (Ok, stat); + ok ((lstrcmpiW(familyName, MicrosoftSansSerif) == 0) || + (lstrcmpiW(familyName,MSSansSerif) == 0), + "Expected Microsoft Sans Serif or MS Sans Serif, got %s\n", + debugstr_w(familyName)); + stat = GdipDeleteFontFamily (*family); + expect (Ok, stat); + + stat = GdipGetGenericFontFamilySerif (family); + expect (Ok, stat); + stat = GdipGetFamilyName (*family, familyName, LANG_NEUTRAL); + expect (Ok, stat); + ok (lstrcmpiW(familyName, TimesNewRoman) == 0, + "Expected Times New Roman, got %s\n", debugstr_w(familyName)); + stat = GdipDeleteFontFamily (*family); + expect (Ok, stat); + + stat = GdipGetGenericFontFamilyMonospace (family); + expect (Ok, stat); + stat = GdipGetFamilyName (*family, familyName, LANG_NEUTRAL); + expect (Ok, stat); + ok (lstrcmpiW(familyName, CourierNew) == 0, + "Expected Courier New, got %s\n", debugstr_w(familyName)); + stat = GdipDeleteFontFamily (*family); + expect (Ok, stat); + + GdipFree (family); +} + START_TEST(font) { struct GdiplusStartupInput gdiplusStartupInput; @@ -106,7 +247,10 @@ START_TEST(font) GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + test_createfont(); test_logfont(); + test_fontfamily(); + test_getgenerics(); GdiplusShutdown(gdiplusToken); } diff --git a/dlls/gdiplus/tests/graphicspath.c b/dlls/gdiplus/tests/graphicspath.c index 672f6da497b..9f65898643d 100644 --- a/dlls/gdiplus/tests/graphicspath.c +++ b/dlls/gdiplus/tests/graphicspath.c @@ -154,14 +154,22 @@ static void test_getpathdata(void) GpPath *path; GpPathData data; GpStatus status; + INT count; GdipCreatePath(FillModeAlternate, &path); status = GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0); expect(Ok, status); + /* Prepare storage. Made by wrapper class. */ + status = GdipGetPointCount(path, &count); + expect(Ok, status); + + data.Count = 2; + data.Types = GdipAlloc(sizeof(BYTE) * count); + data.Points = GdipAlloc(sizeof(PointF) * count); + status = GdipGetPathData(path, &data); expect(Ok, status); - expect((data.Count == 2), TRUE); expect((data.Points[0].X == 5.0) && (data.Points[0].Y == 5.0) && (data.Points[1].X == 100.0) && (data.Points[1].Y == 50.0), TRUE); expect((data.Types[0] == PathPointTypeStart) && (data.Types[1] == PathPointTypeLine), TRUE); @@ -567,6 +575,52 @@ static void test_linei(void) GdipDeletePath(path); } +static path_test_t poly_path[] = { + {5.00, 5.00, PathPointTypeStart, 0, 0}, /*1*/ + {6.00, 8.00, PathPointTypeLine, 0, 0}, /*2*/ + {0.00, 0.00, PathPointTypeStart, 0, 0}, /*3*/ + {10.00, 10.00, PathPointTypeLine, 0, 0}, /*4*/ + {10.00, 20.00, PathPointTypeLine, 0, 0}, /*5*/ + {30.00, 10.00, PathPointTypeLine, 0, 0}, /*6*/ + {20.00, 0.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*7*/ + }; + +static void test_polygon(void) +{ + GpStatus status; + GpPath *path; + GpPointF points[5]; + + points[0].X = 0.0; + points[0].Y = 0.0; + points[1].X = 10.0; + points[1].Y = 10.0; + points[2].X = 10.0; + points[2].Y = 20.0; + points[3].X = 30.0; + points[3].Y = 10.0; + points[4].X = 20.0; + points[4].Y = 0.0; + + /* NULL args */ + status = GdipAddPathPolygon(NULL, points, 5); + expect(InvalidParameter, status); + status = GdipAddPathPolygon(path, NULL, 5); + expect(InvalidParameter, status); + /* Polygon should have 3 points at least */ + status = GdipAddPathPolygon(path, points, 2); + expect(InvalidParameter, status); + + GdipCreatePath(FillModeAlternate, &path); + /* to test how it prolongs not empty path */ + status = GdipAddPathLine(path, 5.0, 5.0, 6.0, 8.0); + expect(Ok, status); + status = GdipAddPathPolygon(path, points, 5); + expect(Ok, status); + /* check resulting path */ + ok_path(path, poly_path, sizeof(poly_path)/sizeof(path_test_t), FALSE); +} + static path_test_t rect_path[] = { {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/ {105.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/ @@ -635,6 +689,7 @@ START_TEST(graphicspath) test_ellipse(); test_linei(); test_rect(); + test_polygon(); GdiplusShutdown(gdiplusToken); } diff --git a/dlls/gdiplus/tests/image.c b/dlls/gdiplus/tests/image.c index a3e76762f06..686fe547fb0 100644 --- a/dlls/gdiplus/tests/image.c +++ b/dlls/gdiplus/tests/image.c @@ -106,6 +106,32 @@ static void test_GetImageDimension(void) GdipDisposeImage((GpImage*)bm); } +static void test_GdipImageGetFrameDimensionsCount(void) +{ + GpBitmap *bm; + GpStatus stat; + const REAL WIDTH = 10.0, HEIGHT = 20.0; + UINT w; + + bm = (GpBitmap*)0xdeadbeef; + stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm); + expect(Ok,stat); + ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n"); + ok(NULL != bm, "Expected bitmap to not be NULL\n"); + + stat = GdipImageGetFrameDimensionsCount(NULL,&w); + expect(InvalidParameter, stat); + + stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,NULL); + expect(InvalidParameter, stat); + + w = -1; + stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,&w); + expect(Ok, stat); + expect(1, w); + GdipDisposeImage((GpImage*)bm); +} + static void test_LoadingImages(void) { GpStatus stat; @@ -466,6 +492,7 @@ START_TEST(image) test_Scan0(); test_GetImageDimension(); + test_GdipImageGetFrameDimensionsCount(); test_LoadingImages(); test_SavingImages(); test_encoders(); diff --git a/dlls/hhctrl.ocx/Ru.rc b/dlls/hhctrl.ocx/Ru.rc index 43330336d2e..a530f80b637 100644 --- a/dlls/hhctrl.ocx/Ru.rc +++ b/dlls/hhctrl.ocx/Ru.rc @@ -38,11 +38,11 @@ BEGIN IDTB_BACK "Íàçàä" IDTB_HOME " íà÷àëî" IDTB_SYNC "Ñèíõðîíèçèðîâàòü" - IDTB_PRINT "Ïå÷ÿòü" + IDTB_PRINT "Ïå÷àòü" IDTB_OPTIONS "Íàñòðîéêè" - IDTB_FORWARD " ïåð¸ä" + IDTB_FORWARD "Âïåð¸ä" IDTB_NOTES "Çàïèñêè" - IDTB_BROWSE_FWD "Ïðîñìîòð â ïåð¸ä" + IDTB_BROWSE_FWD "Ïðîñìîòð âïåð¸ä" IDTB_BROWSE_BACK "Ïðîñìîòð íàçàä" IDTB_CONTENTS "Ñîäåðæàíèå" IDTB_INDEX "Îãëàâëåíèå" diff --git a/dlls/inetcomm/mimeole.c b/dlls/inetcomm/mimeole.c index ee03e92f951..7e9d709f5ce 100644 --- a/dlls/inetcomm/mimeole.c +++ b/dlls/inetcomm/mimeole.c @@ -1629,8 +1629,8 @@ static body_t *create_sub_body(MimeMessage *msg, IStream *pStm, BODYOFFSETS *off IStream *sub_stream; ULARGE_INTEGER start, length; - start.u.LowPart = cur->offsets.cbHeaderStart; - length.u.LowPart = cur->offsets.cbBodyEnd - cur->offsets.cbHeaderStart; + start.QuadPart = cur->offsets.cbHeaderStart; + length.QuadPart = cur->offsets.cbBodyEnd - cur->offsets.cbHeaderStart; create_sub_stream(pStm, start, length, &sub_stream); sub_body = create_sub_body(msg, sub_stream, &cur->offsets, body); IStream_Release(sub_stream); diff --git a/dlls/d3dx9_26/Makefile.in b/dlls/inetmib1/Makefile.in similarity index 68% copy from dlls/d3dx9_26/Makefile.in copy to dlls/inetmib1/Makefile.in index 76de9f0fcd3..3998f0023bf 100644 --- a/dlls/d3dx9_26/Makefile.in +++ b/dlls/inetmib1/Makefile.in @@ -2,11 +2,12 @@ TOPSRCDIR = @top_srcdir@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ -MODULE = d3dx9_26.dll -IMPORTS = d3d9 kernel32 +MODULE = inetmib1.dll +IMPORTS = snmpapi kernel32 +DELAYIMPORTS = iphlpapi C_SRCS = \ - d3dx9_26_main.c + main.c @MAKE_DLL_RULES@ diff --git a/dlls/inetmib1/inetmib1.spec b/dlls/inetmib1/inetmib1.spec new file mode 100644 index 00000000000..dc7b4911fe6 --- /dev/null +++ b/dlls/inetmib1/inetmib1.spec @@ -0,0 +1,4 @@ +@ stdcall SnmpExtensionInit(long ptr ptr) +@ stub SnmpExtensionInitEx +@ stdcall SnmpExtensionQuery(long ptr ptr ptr) +@ stub SnmpExtensionTrap diff --git a/dlls/inetmib1/main.c b/dlls/inetmib1/main.c new file mode 100644 index 00000000000..20fc0b99284 --- /dev/null +++ b/dlls/inetmib1/main.c @@ -0,0 +1,1171 @@ +/* + * Copyright 2008 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include +#include +#include +#include +#include "windef.h" +#include "winbase.h" +#include "snmp.h" +#include "iphlpapi.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(inetmib1); + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); + + switch (fdwReason) + { + case DLL_WINE_PREATTACH: + return FALSE; /* prefer native version */ + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + break; + case DLL_PROCESS_DETACH: + break; + default: + break; + } + + return TRUE; +} + +/** + * Utility functions + */ +static void copyInt(AsnAny *value, void *src) +{ + value->asnType = ASN_INTEGER; + value->asnValue.number = *(DWORD *)src; +} + +static void setStringValue(AsnAny *value, BYTE type, DWORD len, BYTE *str) +{ + AsnAny strValue; + + strValue.asnType = type; + strValue.asnValue.string.stream = str; + strValue.asnValue.string.length = len; + strValue.asnValue.string.dynamic = TRUE; + SnmpUtilAsnAnyCpy(value, &strValue); +} + +static void copyLengthPrecededString(AsnAny *value, void *src) +{ + DWORD len = *(DWORD *)src; + + setStringValue(value, ASN_OCTETSTRING, len, (BYTE *)src + sizeof(DWORD)); +} + +typedef void (*copyValueFunc)(AsnAny *value, void *src); + +struct structToAsnValue +{ + size_t offset; + copyValueFunc copy; +}; + +static AsnInteger32 mapStructEntryToValue(struct structToAsnValue *map, + UINT mapLen, void *record, UINT id, BYTE bPduType, SnmpVarBind *pVarBind) +{ + /* OIDs are 1-based */ + if (!id) + return SNMP_ERRORSTATUS_NOSUCHNAME; + --id; + if (id >= mapLen) + return SNMP_ERRORSTATUS_NOSUCHNAME; + if (!map[id].copy) + return SNMP_ERRORSTATUS_NOSUCHNAME; + map[id].copy(&pVarBind->value, (BYTE *)record + map[id].offset); + return SNMP_ERRORSTATUS_NOERROR; +} + +static void copyIpAddr(AsnAny *value, void *src) +{ + setStringValue(value, ASN_IPADDRESS, sizeof(DWORD), src); +} + +static UINT mib2[] = { 1,3,6,1,2,1 }; +static UINT mib2System[] = { 1,3,6,1,2,1,1 }; + +typedef BOOL (*varqueryfunc)(BYTE bPduType, SnmpVarBind *pVarBind, + AsnInteger32 *pErrorStatus); + +struct mibImplementation +{ + AsnObjectIdentifier name; + void (*init)(void); + varqueryfunc query; +}; + +static UINT mib2IfNumber[] = { 1,3,6,1,2,1,2,1 }; +static PMIB_IFTABLE ifTable; + +static void mib2IfNumberInit(void) +{ + DWORD size = 0, ret = GetIfTable(NULL, &size, FALSE); + + if (ret == ERROR_INSUFFICIENT_BUFFER) + { + ifTable = HeapAlloc(GetProcessHeap(), 0, size); + if (ifTable) + GetIfTable(ifTable, &size, FALSE); + } +} + +static BOOL mib2IfNumberQuery(BYTE bPduType, SnmpVarBind *pVarBind, + AsnInteger32 *pErrorStatus) +{ + AsnObjectIdentifier numberOid = DEFINE_OID(mib2IfNumber); + + TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), + pErrorStatus); + + switch (bPduType) + { + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + if ((bPduType == SNMP_PDU_GET && + !SnmpUtilOidNCmp(&pVarBind->name, &numberOid, numberOid.idLength)) + || SnmpUtilOidNCmp(&pVarBind->name, &numberOid, numberOid.idLength) + < 0) + { + DWORD numIfs = ifTable ? ifTable->dwNumEntries : 0; + + copyInt(&pVarBind->value, &numIfs); + if (bPduType == SNMP_PDU_GETNEXT) + SnmpUtilOidCpy(&pVarBind->name, &numberOid); + *pErrorStatus = SNMP_ERRORSTATUS_NOERROR; + } + else + { + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + /* Caller deals with OID if bPduType == SNMP_PDU_GETNEXT, so don't + * need to set it here. + */ + } + break; + case SNMP_PDU_SET: + *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + break; + default: + FIXME("0x%02x: unsupported PDU type\n", bPduType); + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return TRUE; +} + +static void copyOperStatus(AsnAny *value, void *src) +{ + value->asnType = ASN_INTEGER; + /* The IPHlpApi definition of operational status differs from the MIB2 one, + * so map it to the MIB2 value. + */ + switch (*(DWORD *)src) + { + case MIB_IF_OPER_STATUS_OPERATIONAL: + value->asnValue.number = MIB_IF_ADMIN_STATUS_UP; + break; + case MIB_IF_OPER_STATUS_CONNECTING: + case MIB_IF_OPER_STATUS_CONNECTED: + value->asnValue.number = MIB_IF_ADMIN_STATUS_TESTING; + break; + default: + value->asnValue.number = MIB_IF_ADMIN_STATUS_DOWN; + }; +} + +/* Given an OID and a base OID that it must begin with, finds the item and + * integer instance from the OID. E.g., given an OID foo.1.2 and a base OID + * foo, returns item 1 and instance 2. + * If bPduType is not SNMP_PDU_GETNEXT and either the item or instance is + * missing, returns SNMP_ERRORSTATUS_NOSUCHNAME. + * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item and + * instance, or item 1, instance 1 if either is missing. + */ +static AsnInteger32 getItemAndIntegerInstanceFromOid(AsnObjectIdentifier *oid, + AsnObjectIdentifier *base, BYTE bPduType, UINT *item, UINT *instance) +{ + AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR; + + switch (bPduType) + { + case SNMP_PDU_GETNEXT: + if (SnmpUtilOidNCmp(oid, base, base->idLength) < 0) + { + *item = 1; + *instance = 1; + } + else if (!SnmpUtilOidNCmp(oid, base, base->idLength)) + { + if (oid->idLength == base->idLength || + oid->idLength == base->idLength + 1) + { + /* Either the table or an item within the table is specified, + * but the instance is not. Get the first instance. + */ + *instance = 1; + if (oid->idLength == base->idLength + 1) + *item = oid->ids[base->idLength]; + else + *item = 1; + } + else + { + *item = oid->ids[base->idLength]; + *instance = oid->ids[base->idLength + 1] + 1; + } + } + else + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + break; + default: + if (!SnmpUtilOidNCmp(oid, base, base->idLength)) + { + if (oid->idLength == base->idLength || + oid->idLength == base->idLength + 1) + { + /* Either the table or an item within the table is specified, + * but the instance is not. + */ + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + } + else + { + *item = oid->ids[base->idLength]; + *instance = oid->ids[base->idLength + 1]; + } + } + else + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return ret; +} + +/* Given an OID and a base OID that it must begin with, finds the item from the + * OID. E.g., given an OID foo.1 and a base OID foo, returns item 1. + * If bPduType is not SNMP_PDU_GETNEXT and the item is missing, returns + * SNMP_ERRORSTATUS_NOSUCHNAME. + * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item, or item + * 1 if the item is missing. + */ +static AsnInteger32 getItemFromOid(AsnObjectIdentifier *oid, + AsnObjectIdentifier *base, BYTE bPduType, UINT *item) +{ + AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR; + + switch (bPduType) + { + case SNMP_PDU_GETNEXT: + if (SnmpUtilOidNCmp(oid, base, base->idLength) < 0) + *item = 1; + else if (!SnmpUtilOidNCmp(oid, base, base->idLength)) + { + if (oid->idLength == base->idLength) + { + /* The item is missing, assume the first item */ + *item = 1; + } + else + *item = oid->ids[base->idLength] + 1; + } + else + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + break; + default: + if (!SnmpUtilOidNCmp(oid, base, base->idLength)) + { + if (oid->idLength == base->idLength) + { + /* The item is missing */ + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + } + else + { + *item = oid->ids[base->idLength]; + if (!*item) + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + } + } + else + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return ret; +} + +struct GenericTable +{ + DWORD numEntries; + BYTE entries[1]; +}; + +static DWORD oidToIpAddr(AsnObjectIdentifier *oid) +{ + assert(oid && oid->idLength >= 4); + /* Map the IDs to an IP address in little-endian order */ + return (BYTE)oid->ids[3] << 24 | (BYTE)oid->ids[2] << 16 | + (BYTE)oid->ids[1] << 8 | (BYTE)oid->ids[0]; +} + +typedef void (*oidToKeyFunc)(AsnObjectIdentifier *oid, void *dst); +typedef int (*compareFunc)(const void *key, const void *value); + +static UINT findValueInTable(AsnObjectIdentifier *oid, + struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey, + compareFunc compare) +{ + UINT index = 0; + void *key = HeapAlloc(GetProcessHeap(), 0, tableEntrySize); + + if (key) + { + void *value; + + makeKey(oid, key); + value = bsearch(key, table->entries, table->numEntries, tableEntrySize, + compare); + if (value) + index = ((BYTE *)value - (BYTE *)table->entries) / tableEntrySize + + 1; + HeapFree(GetProcessHeap(), 0, key); + } + return index; +} + +/* Given an OID and a base OID that it must begin with, finds the item and + * element of the table whose IP address matches the instance from the OID. + * E.g., given an OID foo.1.2.3.4.5 and a base OID foo, returns item 1 and the + * index of the entry in the table whose IP address is 2.3.4.5. + * If bPduType is not SNMP_PDU_GETNEXT and either the item or instance is + * missing, returns SNMP_ERRORSTATUS_NOSUCHNAME. + * If bPduType is SNMP_PDU_GETNEXT, returns the successor to the item and + * instance, or item 1, instance 1 if either is missing. + */ +static AsnInteger32 getItemAndIpAddressInstanceFromOid(AsnObjectIdentifier *oid, + AsnObjectIdentifier *base, BYTE bPduType, struct GenericTable *table, + size_t tableEntrySize, oidToKeyFunc makeKey, compareFunc compare, + UINT *item, UINT *instance) +{ + AsnInteger32 ret = SNMP_ERRORSTATUS_NOERROR; + + if (!table) + return SNMP_ERRORSTATUS_NOSUCHNAME; + + switch (bPduType) + { + case SNMP_PDU_GETNEXT: + if (SnmpUtilOidNCmp(oid, base, base->idLength) < 0) + { + /* Return the first item and instance from the table */ + *item = 1; + *instance = 1; + } + else if (!SnmpUtilOidNCmp(oid, base, base->idLength) && + oid->idLength < base->idLength + 5) + { + /* Either the table or an item is specified, but the instance is + * not. + */ + *instance = 1; + if (oid->idLength >= base->idLength + 1) + { + *item = oid->ids[base->idLength]; + if (!*item) + *item = 1; + } + else + *item = 1; + } + else if (!SnmpUtilOidNCmp(oid, base, base->idLength) && + oid->idLength == base->idLength + 5) + { + *item = oid->ids[base->idLength]; + if (!*item) + { + *instance = 1; + *item = 1; + } + else + { + AsnObjectIdentifier ipOid = { 4, oid->ids + base->idLength + 1 + }; + + *instance = findValueInTable(&ipOid, table, tableEntrySize, + makeKey, compare) + 1; + if (*instance > table->numEntries) + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + } + } + else + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + break; + default: + if (!SnmpUtilOidNCmp(oid, base, base->idLength) && + oid->idLength == base->idLength + 5) + { + *item = oid->ids[base->idLength]; + if (!*item) + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + else + { + AsnObjectIdentifier ipOid = { 4, oid->ids + base->idLength + 1 + }; + + *instance = findValueInTable(&ipOid, table, tableEntrySize, + makeKey, compare); + if (!*instance) + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + } + } + else + ret = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return ret; +} + +static void setOidWithItem(AsnObjectIdentifier *dst, AsnObjectIdentifier *base, + UINT item) +{ + UINT id; + AsnObjectIdentifier oid; + + SnmpUtilOidCpy(dst, base); + oid.idLength = 1; + oid.ids = &id; + id = item; + SnmpUtilOidAppend(dst, &oid); +} + +static void setOidWithItemAndIpAddr(AsnObjectIdentifier *dst, + AsnObjectIdentifier *base, UINT item, DWORD addr) +{ + UINT id; + BYTE *ptr; + AsnObjectIdentifier oid; + + setOidWithItem(dst, base, item); + oid.idLength = 1; + oid.ids = &id; + for (ptr = (BYTE *)&addr; ptr < (BYTE *)&addr + sizeof(DWORD); ptr++) + { + id = *ptr; + SnmpUtilOidAppend(dst, &oid); + } +} + +static void setOidWithItemAndInteger(AsnObjectIdentifier *dst, + AsnObjectIdentifier *base, UINT item, UINT instance) +{ + AsnObjectIdentifier oid; + + setOidWithItem(dst, base, item); + oid.idLength = 1; + oid.ids = &instance; + SnmpUtilOidAppend(dst, &oid); +} + +static struct structToAsnValue mib2IfEntryMap[] = { + { FIELD_OFFSET(MIB_IFROW, dwIndex), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwDescrLen), copyLengthPrecededString }, + { FIELD_OFFSET(MIB_IFROW, dwType), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwMtu), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwSpeed), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwPhysAddrLen), copyLengthPrecededString }, + { FIELD_OFFSET(MIB_IFROW, dwAdminStatus), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwOperStatus), copyOperStatus }, + { FIELD_OFFSET(MIB_IFROW, dwLastChange), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwInOctets), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwInUcastPkts), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwInNUcastPkts), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwInDiscards), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwInErrors), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwInUnknownProtos), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwOutOctets), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwOutUcastPkts), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwOutNUcastPkts), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwOutDiscards), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwOutErrors), copyInt }, + { FIELD_OFFSET(MIB_IFROW, dwOutQLen), copyInt }, +}; + +static UINT mib2IfEntry[] = { 1,3,6,1,2,1,2,2,1 }; + +static BOOL mib2IfEntryQuery(BYTE bPduType, SnmpVarBind *pVarBind, + AsnInteger32 *pErrorStatus) +{ + AsnObjectIdentifier entryOid = DEFINE_OID(mib2IfEntry); + + TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), + pErrorStatus); + + switch (bPduType) + { + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + if (!ifTable) + { + /* There is no interface present, so let the caller deal + * with finding the successor. + */ + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + } + else + { + UINT tableIndex = 0, item = 0; + + *pErrorStatus = getItemAndIntegerInstanceFromOid(&pVarBind->name, + &entryOid, bPduType, &item, &tableIndex); + if (!*pErrorStatus) + { + assert(tableIndex); + assert(item); + if (tableIndex > ifTable->dwNumEntries) + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + else + { + *pErrorStatus = mapStructEntryToValue(mib2IfEntryMap, + DEFINE_SIZEOF(mib2IfEntryMap), + &ifTable->table[tableIndex - 1], item, bPduType, + pVarBind); + if (bPduType == SNMP_PDU_GETNEXT) + setOidWithItemAndInteger(&pVarBind->name, &entryOid, + item, tableIndex); + } + } + } + break; + case SNMP_PDU_SET: + *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + break; + default: + FIXME("0x%02x: unsupported PDU type\n", bPduType); + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return TRUE; +} + +static UINT mib2Ip[] = { 1,3,6,1,2,1,4 }; +static MIB_IPSTATS ipStats; + +static void mib2IpStatsInit(void) +{ + GetIpStatistics(&ipStats); +} + +static struct structToAsnValue mib2IpMap[] = { + { FIELD_OFFSET(MIB_IPSTATS, dwForwarding), copyInt }, /* 1 */ + { FIELD_OFFSET(MIB_IPSTATS, dwDefaultTTL), copyInt }, /* 2 */ + { FIELD_OFFSET(MIB_IPSTATS, dwInReceives), copyInt }, /* 3 */ + { FIELD_OFFSET(MIB_IPSTATS, dwInHdrErrors), copyInt }, /* 4 */ + { FIELD_OFFSET(MIB_IPSTATS, dwInAddrErrors), copyInt }, /* 5 */ + { FIELD_OFFSET(MIB_IPSTATS, dwForwDatagrams), copyInt }, /* 6 */ + { FIELD_OFFSET(MIB_IPSTATS, dwInUnknownProtos), copyInt }, /* 7 */ + { FIELD_OFFSET(MIB_IPSTATS, dwInDiscards), copyInt }, /* 8 */ + { FIELD_OFFSET(MIB_IPSTATS, dwInDelivers), copyInt }, /* 9 */ + { FIELD_OFFSET(MIB_IPSTATS, dwOutRequests), copyInt }, /* 10 */ + { FIELD_OFFSET(MIB_IPSTATS, dwOutDiscards), copyInt }, /* 11 */ + { FIELD_OFFSET(MIB_IPSTATS, dwOutNoRoutes), copyInt }, /* 12 */ + { FIELD_OFFSET(MIB_IPSTATS, dwReasmTimeout), copyInt }, /* 13 */ + { FIELD_OFFSET(MIB_IPSTATS, dwReasmReqds), copyInt }, /* 14 */ + { FIELD_OFFSET(MIB_IPSTATS, dwReasmOks), copyInt }, /* 15 */ + { FIELD_OFFSET(MIB_IPSTATS, dwReasmFails), copyInt }, /* 16 */ + { FIELD_OFFSET(MIB_IPSTATS, dwFragOks), copyInt }, /* 17 */ + { FIELD_OFFSET(MIB_IPSTATS, dwFragFails), copyInt }, /* 18 */ + { FIELD_OFFSET(MIB_IPSTATS, dwFragCreates), copyInt }, /* 19 */ + { 0, NULL }, /* 20: not used, IP addr table */ + { 0, NULL }, /* 21: not used, route table */ + { 0, NULL }, /* 22: not used, net to media (ARP) table */ + { FIELD_OFFSET(MIB_IPSTATS, dwRoutingDiscards), copyInt }, /* 23 */ +}; + +static BOOL mib2IpStatsQuery(BYTE bPduType, SnmpVarBind *pVarBind, + AsnInteger32 *pErrorStatus) +{ + AsnObjectIdentifier myOid = DEFINE_OID(mib2Ip); + UINT item = 0; + + TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), + pErrorStatus); + + switch (bPduType) + { + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType, + &item); + if (!*pErrorStatus) + { + *pErrorStatus = mapStructEntryToValue(mib2IpMap, + DEFINE_SIZEOF(mib2IpMap), &ipStats, item, bPduType, pVarBind); + if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) + setOidWithItem(&pVarBind->name, &myOid, item); + } + break; + case SNMP_PDU_SET: + *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + break; + default: + FIXME("0x%02x: unsupported PDU type\n", bPduType); + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return TRUE; +} + +static UINT mib2IpAddr[] = { 1,3,6,1,2,1,4,20,1 }; +static PMIB_IPADDRTABLE ipAddrTable; + +static struct structToAsnValue mib2IpAddrMap[] = { + { FIELD_OFFSET(MIB_IPADDRROW, dwAddr), copyIpAddr }, + { FIELD_OFFSET(MIB_IPADDRROW, dwIndex), copyInt }, + { FIELD_OFFSET(MIB_IPADDRROW, dwMask), copyIpAddr }, + { FIELD_OFFSET(MIB_IPADDRROW, dwBCastAddr), copyInt }, + { FIELD_OFFSET(MIB_IPADDRROW, dwReasmSize), copyInt }, +}; + +static void mib2IpAddrInit(void) +{ + DWORD size = 0, ret = GetIpAddrTable(NULL, &size, TRUE); + + if (ret == ERROR_INSUFFICIENT_BUFFER) + { + ipAddrTable = HeapAlloc(GetProcessHeap(), 0, size); + if (ipAddrTable) + GetIpAddrTable(ipAddrTable, &size, TRUE); + } +} + +static void oidToIpAddrRow(AsnObjectIdentifier *oid, void *dst) +{ + MIB_IPADDRROW *row = dst; + + row->dwAddr = oidToIpAddr(oid); +} + +static int compareIpAddrRow(const void *a, const void *b) +{ + const MIB_IPADDRROW *key = a, *value = b; + + return key->dwAddr - value->dwAddr; +} + +static BOOL mib2IpAddrQuery(BYTE bPduType, SnmpVarBind *pVarBind, + AsnInteger32 *pErrorStatus) +{ + AsnObjectIdentifier myOid = DEFINE_OID(mib2IpAddr); + UINT tableIndex = 0, item = 0; + + TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), + pErrorStatus); + + switch (bPduType) + { + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + *pErrorStatus = getItemAndIpAddressInstanceFromOid(&pVarBind->name, + &myOid, bPduType, (struct GenericTable *)ipAddrTable, + sizeof(MIB_IPADDRROW), oidToIpAddrRow, compareIpAddrRow, &item, + &tableIndex); + if (!*pErrorStatus) + { + assert(tableIndex); + assert(item); + *pErrorStatus = mapStructEntryToValue(mib2IpAddrMap, + DEFINE_SIZEOF(mib2IpAddrMap), + &ipAddrTable->table[tableIndex - 1], item, bPduType, pVarBind); + if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) + setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item, + ipAddrTable->table[tableIndex - 1].dwAddr); + } + break; + case SNMP_PDU_SET: + *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + break; + default: + FIXME("0x%02x: unsupported PDU type\n", bPduType); + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return TRUE; +} + +static UINT mib2IpRoute[] = { 1,3,6,1,2,1,4,21,1 }; +static PMIB_IPFORWARDTABLE ipRouteTable; + +static struct structToAsnValue mib2IpRouteMap[] = { + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardDest), copyIpAddr }, + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardIfIndex), copyInt }, + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric1), copyInt }, + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric2), copyInt }, + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric3), copyInt }, + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric4), copyInt }, + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardNextHop), copyIpAddr }, + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardType), copyInt }, + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardProto), copyInt }, + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardAge), copyInt }, + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMask), copyIpAddr }, + { FIELD_OFFSET(MIB_IPFORWARDROW, dwForwardMetric5), copyInt }, +}; + +static void mib2IpRouteInit(void) +{ + DWORD size = 0, ret = GetIpForwardTable(NULL, &size, TRUE); + + if (ret == ERROR_INSUFFICIENT_BUFFER) + { + ipRouteTable = HeapAlloc(GetProcessHeap(), 0, size); + if (ipRouteTable) + GetIpForwardTable(ipRouteTable, &size, TRUE); + } +} + +static void oidToIpForwardRow(AsnObjectIdentifier *oid, void *dst) +{ + MIB_IPFORWARDROW *row = dst; + + row->dwForwardDest = oidToIpAddr(oid); +} + +static int compareIpForwardRow(const void *a, const void *b) +{ + const MIB_IPFORWARDROW *key = a, *value = b; + + return key->dwForwardDest - value->dwForwardDest; +} + +static BOOL mib2IpRouteQuery(BYTE bPduType, SnmpVarBind *pVarBind, + AsnInteger32 *pErrorStatus) +{ + AsnObjectIdentifier myOid = DEFINE_OID(mib2IpRoute); + UINT tableIndex = 0, item = 0; + + TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), + pErrorStatus); + + switch (bPduType) + { + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + *pErrorStatus = getItemAndIpAddressInstanceFromOid(&pVarBind->name, + &myOid, bPduType, (struct GenericTable *)ipRouteTable, + sizeof(MIB_IPFORWARDROW), oidToIpForwardRow, compareIpForwardRow, + &item, &tableIndex); + if (!*pErrorStatus) + { + assert(tableIndex); + assert(item); + *pErrorStatus = mapStructEntryToValue(mib2IpRouteMap, + DEFINE_SIZEOF(mib2IpRouteMap), + &ipRouteTable->table[tableIndex - 1], item, bPduType, pVarBind); + if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) + setOidWithItemAndIpAddr(&pVarBind->name, &myOid, item, + ipRouteTable->table[tableIndex - 1].dwForwardDest); + } + break; + case SNMP_PDU_SET: + *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + break; + default: + FIXME("0x%02x: unsupported PDU type\n", bPduType); + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return TRUE; +} + +static UINT mib2IpNet[] = { 1,3,6,1,2,1,4,22,1 }; +static PMIB_IPNETTABLE ipNetTable; + +static struct structToAsnValue mib2IpNetMap[] = { + { FIELD_OFFSET(MIB_IPNETROW, dwIndex), copyInt }, + { FIELD_OFFSET(MIB_IPNETROW, dwPhysAddrLen), copyLengthPrecededString }, + { FIELD_OFFSET(MIB_IPNETROW, dwAddr), copyIpAddr }, + { FIELD_OFFSET(MIB_IPNETROW, dwType), copyInt }, +}; + +static void mib2IpNetInit(void) +{ + DWORD size = 0, ret = GetIpNetTable(NULL, &size, FALSE); + + if (ret == ERROR_INSUFFICIENT_BUFFER) + { + ipNetTable = HeapAlloc(GetProcessHeap(), 0, size); + if (ipNetTable) + GetIpNetTable(ipNetTable, &size, FALSE); + } +} + +static BOOL mib2IpNetQuery(BYTE bPduType, SnmpVarBind *pVarBind, + AsnInteger32 *pErrorStatus) +{ + AsnObjectIdentifier myOid = DEFINE_OID(mib2IpNet); + + TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), + pErrorStatus); + + switch (bPduType) + { + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + if (!ipNetTable) + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + else + { + UINT tableIndex = 0, item = 0; + + *pErrorStatus = getItemAndIntegerInstanceFromOid(&pVarBind->name, + &myOid, bPduType, &item, &tableIndex); + if (!*pErrorStatus) + { + assert(tableIndex); + assert(item); + if (tableIndex > ipNetTable->dwNumEntries) + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + else + { + *pErrorStatus = mapStructEntryToValue(mib2IpNetMap, + DEFINE_SIZEOF(mib2IpNetMap), + &ipNetTable[tableIndex - 1], item, bPduType, pVarBind); + if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) + setOidWithItemAndInteger(&pVarBind->name, &myOid, item, + tableIndex); + } + } + } + break; + case SNMP_PDU_SET: + *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + break; + default: + FIXME("0x%02x: unsupported PDU type\n", bPduType); + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return TRUE; +} + +static UINT mib2Icmp[] = { 1,3,6,1,2,1,5 }; +static MIB_ICMP icmpStats; + +static void mib2IcmpInit(void) +{ + GetIcmpStatistics(&icmpStats); +} + +static struct structToAsnValue mib2IcmpMap[] = { + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwMsgs), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwErrors), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwDestUnreachs), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwTimeExcds), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwParmProbs), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwSrcQuenchs), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwRedirects), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwEchos), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwEchoReps), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwTimestamps), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwTimestampReps), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwAddrMasks), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpInStats.dwAddrMaskReps), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwMsgs), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwErrors), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwDestUnreachs), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwTimeExcds), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwParmProbs), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwSrcQuenchs), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwRedirects), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwEchos), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwEchoReps), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwTimestamps), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwTimestampReps), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwAddrMasks), copyInt }, + { FIELD_OFFSET(MIBICMPINFO, icmpOutStats.dwAddrMaskReps), copyInt }, +}; + +static BOOL mib2IcmpQuery(BYTE bPduType, SnmpVarBind *pVarBind, + AsnInteger32 *pErrorStatus) +{ + AsnObjectIdentifier myOid = DEFINE_OID(mib2Icmp); + UINT item = 0; + + TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), + pErrorStatus); + + switch (bPduType) + { + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType, + &item); + if (!*pErrorStatus) + { + *pErrorStatus = mapStructEntryToValue(mib2IcmpMap, + DEFINE_SIZEOF(mib2IcmpMap), &icmpStats, item, bPduType, + pVarBind); + if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) + setOidWithItem(&pVarBind->name, &myOid, item); + } + break; + case SNMP_PDU_SET: + *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + break; + default: + FIXME("0x%02x: unsupported PDU type\n", bPduType); + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return TRUE; +} + +static UINT mib2Tcp[] = { 1,3,6,1,2,1,6 }; +static MIB_TCPSTATS tcpStats; + +static void mib2TcpInit(void) +{ + GetTcpStatistics(&tcpStats); +} + +static struct structToAsnValue mib2TcpMap[] = { + { FIELD_OFFSET(MIB_TCPSTATS, dwRtoAlgorithm), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwRtoMin), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwRtoMax), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwMaxConn), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwActiveOpens), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwPassiveOpens), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwAttemptFails), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwEstabResets), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwCurrEstab), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwInSegs), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwOutSegs), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwRetransSegs), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwInErrs), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwOutRsts), copyInt }, + { FIELD_OFFSET(MIB_TCPSTATS, dwNumConns), copyInt }, +}; + +static BOOL mib2TcpQuery(BYTE bPduType, SnmpVarBind *pVarBind, + AsnInteger32 *pErrorStatus) +{ + AsnObjectIdentifier myOid = DEFINE_OID(mib2Tcp); + UINT item = 0; + + TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), + pErrorStatus); + + switch (bPduType) + { + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType, + &item); + if (!*pErrorStatus) + { + *pErrorStatus = mapStructEntryToValue(mib2TcpMap, + DEFINE_SIZEOF(mib2TcpMap), &tcpStats, item, bPduType, pVarBind); + if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) + setOidWithItem(&pVarBind->name, &myOid, item); + } + break; + case SNMP_PDU_SET: + *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + break; + default: + FIXME("0x%02x: unsupported PDU type\n", bPduType); + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return TRUE; +} + +static UINT mib2Udp[] = { 1,3,6,1,2,1,7 }; +static MIB_UDPSTATS udpStats; + +static void mib2UdpInit(void) +{ + GetUdpStatistics(&udpStats); +} + +static struct structToAsnValue mib2UdpMap[] = { + { FIELD_OFFSET(MIB_UDPSTATS, dwInDatagrams), copyInt }, + { FIELD_OFFSET(MIB_UDPSTATS, dwNoPorts), copyInt }, + { FIELD_OFFSET(MIB_UDPSTATS, dwInErrors), copyInt }, + { FIELD_OFFSET(MIB_UDPSTATS, dwOutDatagrams), copyInt }, +}; + +static BOOL mib2UdpQuery(BYTE bPduType, SnmpVarBind *pVarBind, + AsnInteger32 *pErrorStatus) +{ + AsnObjectIdentifier myOid = DEFINE_OID(mib2Udp); + UINT item; + + TRACE("(0x%02x, %s, %p)\n", bPduType, SnmpUtilOidToA(&pVarBind->name), + pErrorStatus); + + switch (bPduType) + { + case SNMP_PDU_GET: + case SNMP_PDU_GETNEXT: + *pErrorStatus = getItemFromOid(&pVarBind->name, &myOid, bPduType, + &item); + if (!*pErrorStatus) + { + *pErrorStatus = mapStructEntryToValue(mib2UdpMap, + DEFINE_SIZEOF(mib2UdpMap), &udpStats, item, bPduType, pVarBind); + if (!*pErrorStatus && bPduType == SNMP_PDU_GETNEXT) + setOidWithItem(&pVarBind->name, &myOid, item); + } + break; + case SNMP_PDU_SET: + *pErrorStatus = SNMP_ERRORSTATUS_READONLY; + break; + default: + FIXME("0x%02x: unsupported PDU type\n", bPduType); + *pErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME; + } + return TRUE; +} + +/* This list MUST BE lexicographically sorted */ +static struct mibImplementation supportedIDs[] = { + { DEFINE_OID(mib2IfNumber), mib2IfNumberInit, mib2IfNumberQuery }, + { DEFINE_OID(mib2IfEntry), NULL, mib2IfEntryQuery }, + { DEFINE_OID(mib2Ip), mib2IpStatsInit, mib2IpStatsQuery }, + { DEFINE_OID(mib2IpAddr), mib2IpAddrInit, mib2IpAddrQuery }, + { DEFINE_OID(mib2IpRoute), mib2IpRouteInit, mib2IpRouteQuery }, + { DEFINE_OID(mib2IpNet), mib2IpNetInit, mib2IpNetQuery }, + { DEFINE_OID(mib2Icmp), mib2IcmpInit, mib2IcmpQuery }, + { DEFINE_OID(mib2Tcp), mib2TcpInit, mib2TcpQuery }, + { DEFINE_OID(mib2Udp), mib2UdpInit, mib2UdpQuery }, +}; +static UINT minSupportedIDLength; + +BOOL WINAPI SnmpExtensionInit(DWORD dwUptimeReference, + HANDLE *phSubagentTrapEvent, AsnObjectIdentifier *pFirstSupportedRegion) +{ + AsnObjectIdentifier myOid = DEFINE_OID(mib2System); + UINT i; + + TRACE("(%d, %p, %p)\n", dwUptimeReference, phSubagentTrapEvent, + pFirstSupportedRegion); + + minSupportedIDLength = UINT_MAX; + for (i = 0; i < sizeof(supportedIDs) / sizeof(supportedIDs[0]); i++) + { + if (supportedIDs[i].init) + supportedIDs[i].init(); + if (supportedIDs[i].name.idLength < minSupportedIDLength) + minSupportedIDLength = supportedIDs[i].name.idLength; + } + *phSubagentTrapEvent = NULL; + SnmpUtilOidCpy(pFirstSupportedRegion, &myOid); + return TRUE; +} + +static struct mibImplementation *findSupportedQuery(UINT *ids, UINT idLength, + UINT *matchingIndex) +{ + int indexHigh = DEFINE_SIZEOF(supportedIDs) - 1, indexLow = 0, i; + struct mibImplementation *impl = NULL; + AsnObjectIdentifier oid1 = { idLength, ids}; + + if (!idLength) + return NULL; + for (i = (indexLow + indexHigh) / 2; !impl && indexLow <= indexHigh; + i = (indexLow + indexHigh) / 2) + { + INT cmp; + + cmp = SnmpUtilOidNCmp(&oid1, &supportedIDs[i].name, idLength); + if (!cmp) + { + impl = &supportedIDs[i]; + *matchingIndex = i; + } + else if (cmp > 0) + indexLow = i + 1; + else + indexHigh = i - 1; + } + return impl; +} + +BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, + AsnInteger32 *pErrorStatus, AsnInteger32 *pErrorIndex) +{ + AsnObjectIdentifier mib2oid = DEFINE_OID(mib2); + AsnInteger32 error = SNMP_ERRORSTATUS_NOERROR, errorIndex = 0; + UINT i; + + TRACE("(0x%02x, %p, %p, %p)\n", bPduType, pVarBindList, + pErrorStatus, pErrorIndex); + + for (i = 0; !error && i < pVarBindList->len; i++) + { + /* Ignore any OIDs not in MIB2 */ + if (!SnmpUtilOidNCmp(&pVarBindList->list[i].name, &mib2oid, + mib2oid.idLength)) + { + struct mibImplementation *impl = NULL; + UINT len, matchingIndex = 0; + + TRACE("%s\n", SnmpUtilOidToA(&pVarBindList->list[i].name)); + /* Search for an implementation matching as many octets as possible + */ + for (len = pVarBindList->list[i].name.idLength; + len >= minSupportedIDLength && !impl; len--) + impl = findSupportedQuery(pVarBindList->list[i].name.ids, len, + &matchingIndex); + if (impl && impl->query) + impl->query(bPduType, &pVarBindList->list[i], &error); + else + error = SNMP_ERRORSTATUS_NOSUCHNAME; + if (error == SNMP_ERRORSTATUS_NOSUCHNAME && + bPduType == SNMP_PDU_GETNEXT) + { + /* GetNext is special: it finds the successor to the given OID, + * so we have to continue until an implementation handles the + * query or we exhaust the table of supported OIDs. + */ + for (; error == SNMP_ERRORSTATUS_NOSUCHNAME && + matchingIndex < DEFINE_SIZEOF(supportedIDs); + matchingIndex++) + { + error = SNMP_ERRORSTATUS_NOERROR; + impl = &supportedIDs[matchingIndex]; + if (impl->query) + impl->query(bPduType, &pVarBindList->list[i], &error); + else + error = SNMP_ERRORSTATUS_NOSUCHNAME; + } + /* If the query still isn't resolved, set the OID to the + * successor to the last entry in the table. + */ + if (error == SNMP_ERRORSTATUS_NOSUCHNAME) + { + SnmpUtilOidFree(&pVarBindList->list[i].name); + SnmpUtilOidCpy(&pVarBindList->list[i].name, + &supportedIDs[matchingIndex - 1].name); + pVarBindList->list[i].name.ids[ + pVarBindList->list[i].name.idLength - 1] += 1; + } + } + if (error) + errorIndex = i + 1; + } + } + *pErrorStatus = error; + *pErrorIndex = errorIndex; + return TRUE; +} diff --git a/dlls/riched20/tests/Makefile.in b/dlls/inetmib1/tests/Makefile.in similarity index 72% copy from dlls/riched20/tests/Makefile.in copy to dlls/inetmib1/tests/Makefile.in index 74a5686bf38..bd6f1444bea 100644 --- a/dlls/riched20/tests/Makefile.in +++ b/dlls/inetmib1/tests/Makefile.in @@ -2,11 +2,11 @@ TOPSRCDIR = @top_srcdir@ TOPOBJDIR = ../../.. SRCDIR = @srcdir@ VPATH = @srcdir@ -TESTDLL = riched20.dll -IMPORTS = ole32 user32 gdi32 kernel32 +TESTDLL = inetmib1.dll +IMPORTS = snmpapi kernel32 CTESTS = \ - editor.c + main.c @MAKE_TEST_RULES@ diff --git a/dlls/inetmib1/tests/main.c b/dlls/inetmib1/tests/main.c new file mode 100644 index 00000000000..012d6d2c458 --- /dev/null +++ b/dlls/inetmib1/tests/main.c @@ -0,0 +1,366 @@ +/* + * Copyright 2008 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include +#include +#include +#include +#include + +#include "wine/test.h" + +static HMODULE inetmib1; + +static void testInit(void) +{ + BOOL (WINAPI *pInit)(DWORD, HANDLE *, AsnObjectIdentifier *); + BOOL ret; + HANDLE event; + AsnObjectIdentifier oid; + + pInit = (void *)GetProcAddress(inetmib1, "SnmpExtensionInit"); + if (!pInit) + { + skip("no SnmpExtensionInit\n"); + return; + } + /* Crash + ret = pInit(0, NULL, NULL); + ret = pInit(0, NULL, &oid); + ret = pInit(0, &event, NULL); + */ + ret = pInit(0, &event, &oid); + ok(ret, "SnmpExtensionInit failed: %d\n", GetLastError()); + ok(!strcmp("1.3.6.1.2.1.1", SnmpUtilOidToA(&oid)), + "Expected 1.3.6.1.2.1.1, got %s\n", SnmpUtilOidToA(&oid)); +} + +static void testQuery(void) +{ + BOOL (WINAPI *pQuery)(BYTE, SnmpVarBindList *, AsnInteger32 *, + AsnInteger32 *); + BOOL ret, moreData; + SnmpVarBindList list; + AsnInteger32 error, index; + UINT bogus[] = { 1,2,3,4 }; + UINT mib2System[] = { 1,3,6,1,2,1,1 }; + UINT mib2If[] = { 1,3,6,1,2,1,2 }; + UINT mib2IfTable[] = { 1,3,6,1,2,1,2,2 }; + UINT mib2IfDescr[] = { 1,3,6,1,2,1,2,2,1,2 }; + UINT mib2IfAdminStatus[] = { 1,3,6,1,2,1,2,2,1,7 }; + UINT mib2IfOperStatus[] = { 1,3,6,1,2,1,2,2,1,8 }; + UINT mib2IpAddr[] = { 1,3,6,1,2,1,4,20,1,1 }; + UINT mib2IpRouteTable[] = { 1,3,6,1,2,1,4,21,1,1 }; + SnmpVarBind vars[3], vars2[3]; + UINT entry; + + pQuery = (void *)GetProcAddress(inetmib1, "SnmpExtensionQuery"); + if (!pQuery) + { + skip("couldn't find SnmpExtensionQuery\n"); + return; + } + /* Crash + ret = pQuery(0, NULL, NULL, NULL); + ret = pQuery(0, NULL, &error, NULL); + ret = pQuery(0, NULL, NULL, &index); + ret = pQuery(0, &list, NULL, NULL); + ret = pQuery(0, &list, &error, NULL); + */ + + /* An empty list succeeds */ + list.len = 0; + error = 0xdeadbeef; + index = 0xdeadbeef; + ret = pQuery(SNMP_PDU_GET, &list, &error, &index); + ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError()); + ok(error == SNMP_ERRORSTATUS_NOERROR, + "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); + ok(index == 0, "expected index 0, got %d\n", index); + + /* Oddly enough, this "succeeds," even though the OID is clearly + * unsupported. + */ + vars[0].name.idLength = sizeof(bogus) / sizeof(bogus[0]); + vars[0].name.ids = bogus; + vars[0].value.asnType = 0; + list.len = 1; + list.list = vars; + SetLastError(0xdeadbeef); + error = 0xdeadbeef; + index = 0xdeadbeef; + ret = pQuery(SNMP_PDU_GET, &list, &error, &index); + ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError()); + ok(error == SNMP_ERRORSTATUS_NOERROR, + "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); + ok(index == 0, "expected index 0, got %d\n", index); + /* The OID isn't changed either: */ + ok(!strcmp("1.2.3.4", SnmpUtilOidToA(&vars[0].name)), + "expected 1.2.3.4, got %s\n", SnmpUtilOidToA(&vars[0].name)); + + /* The table is not an accessible variable, so it fails */ + vars[0].name.idLength = sizeof(mib2IfTable) / sizeof(mib2IfTable[0]); + vars[0].name.ids = mib2IfTable; + SetLastError(0xdeadbeef); + error = 0xdeadbeef; + index = 0xdeadbeef; + ret = pQuery(SNMP_PDU_GET, &list, &error, &index); + ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError()); + ok(error == SNMP_ERRORSTATUS_NOSUCHNAME, + "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error); + /* The index is 1-based rather than 0-based */ + ok(index == 1, "expected index 1, got %d\n", index); + + /* A Get fails on something that specifies a table (but not a particular + * entry in it)... + */ + vars[0].name.idLength = sizeof(mib2IfDescr) / sizeof(mib2IfDescr[0]); + vars[0].name.ids = mib2IfDescr; + vars[1].name.idLength = + sizeof(mib2IfAdminStatus) / sizeof(mib2IfAdminStatus[0]); + vars[1].name.ids = mib2IfAdminStatus; + vars[2].name.idLength = + sizeof(mib2IfOperStatus) / sizeof(mib2IfOperStatus[0]); + vars[2].name.ids = mib2IfOperStatus; + list.len = 3; + SetLastError(0xdeadbeef); + error = 0xdeadbeef; + index = 0xdeadbeef; + ret = pQuery(SNMP_PDU_GET, &list, &error, &index); + ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError()); + ok(error == SNMP_ERRORSTATUS_NOSUCHNAME, + "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error); + ok(index == 1, "expected index 1, got %d\n", index); + /* but a GetNext succeeds with the same values, because GetNext gets the + * entry after the specified OID, not the entry specified by it. The + * successor to the table is the first entry in the table. + * The OIDs need to be allocated, because GetNext modifies them to indicate + * the end of data. + */ + SnmpUtilOidCpy(&vars2[0].name, &vars[0].name); + SnmpUtilOidCpy(&vars2[1].name, &vars[1].name); + SnmpUtilOidCpy(&vars2[2].name, &vars[2].name); + list.list = vars2; + moreData = TRUE; + entry = 1; + do { + SetLastError(0xdeadbeef); + error = 0xdeadbeef; + index = 0xdeadbeef; + ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index); + ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError()); + ok(error == SNMP_ERRORSTATUS_NOERROR, + "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); + ok(index == 0, "expected index 0, got %d\n", index); + if (!ret) + moreData = FALSE; + else if (error) + moreData = FALSE; + else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, + vars[0].name.idLength)) + moreData = FALSE; + else if (SnmpUtilOidNCmp(&vars2[1].name, &vars[1].name, + vars[1].name.idLength)) + moreData = FALSE; + else if (SnmpUtilOidNCmp(&vars2[2].name, &vars[2].name, + vars[2].name.idLength)) + moreData = FALSE; + if (moreData) + { + /* Check the OIDs. For these types of values (display strings and + * integers) they increase by 1 for each element of the table. + */ + ok(vars2[0].name.idLength == vars[0].name.idLength + 1, + "expected length %d, got %d\n", vars[0].name.idLength + 1, + vars2[0].name.idLength); + ok(vars2[0].name.ids[vars2[0].name.idLength - 1] == entry, + "expected %d, got %d\n", entry, + vars2[0].name.ids[vars2[0].name.idLength - 1]); + ok(vars2[1].name.idLength == vars[1].name.idLength + 1, + "expected length %d, got %d\n", vars[1].name.idLength + 1, + vars2[1].name.idLength); + ok(vars2[1].name.ids[vars2[1].name.idLength - 1] == entry, + "expected %d, got %d\n", entry, + vars2[1].name.ids[vars2[1].name.idLength - 1]); + ok(vars2[2].name.idLength == vars[2].name.idLength + 1, + "expected length %d, got %d\n", vars[2].name.idLength + 1, + vars2[2].name.idLength); + ok(vars2[2].name.ids[vars2[2].name.idLength - 1] == entry, + "expected %d, got %d\n", entry, + vars2[2].name.ids[vars2[2].name.idLength - 1]); + ++entry; + /* Check the types while we're at it */ + ok(vars2[0].value.asnType == ASN_OCTETSTRING, + "expected ASN_OCTETSTRING, got %02x\n", vars2[0].value.asnType); + ok(vars2[1].value.asnType == ASN_INTEGER, + "expected ASN_INTEGER, got %02x\n", vars2[1].value.asnType); + ok(vars2[2].value.asnType == ASN_INTEGER, + "expected ASN_INTEGER, got %02x\n", vars2[2].value.asnType); + /* Check that the operational status of an interface correctly + * follows the MIB2 definition of it, rather than the values + * defined for IPHlpApi's dwOperStatus field. + */ + ok(vars2[2].value.asnValue.unsigned32 <= 2, + "expected a value of 0, 1, or 2, got %u\n", + vars2[2].value.asnValue.unsigned32); + } + } while (moreData); + SnmpUtilVarBindFree(&vars2[0]); + SnmpUtilVarBindFree(&vars2[1]); + SnmpUtilVarBindFree(&vars2[2]); + + /* Even though SnmpExtensionInit says this DLL supports the MIB2 system + * variables, the first variable it returns a value for is the first + * interface. + */ + vars[0].name.idLength = sizeof(mib2System) / sizeof(mib2System[0]); + vars[0].name.ids = mib2System; + SnmpUtilOidCpy(&vars2[0].name, &vars[0].name); + vars2[0].value.asnType = 0; + list.len = 1; + list.list = vars2; + moreData = TRUE; + ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index); + ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError()); + ok(error == SNMP_ERRORSTATUS_NOERROR, + "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); + ok(index == 0, "expected index 0, got %d\n", index); + vars[0].name.idLength = sizeof(mib2If) / sizeof(mib2If[0]); + vars[0].name.ids = mib2If; + ok(!SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, vars[0].name.idLength), + "expected 1.3.6.1.2.1.2, got %s\n", SnmpUtilOidToA(&vars2[0].name)); + SnmpUtilVarBindFree(&vars2[0]); + + /* Check the type and OIDs of the IP address table */ + vars[0].name.idLength = sizeof(mib2IpAddr) / sizeof(mib2IpAddr[0]); + vars[0].name.ids = mib2IpAddr; + SnmpUtilOidCpy(&vars2[0].name, &vars[0].name); + vars2[0].value.asnType = 0; + list.len = 1; + list.list = vars2; + moreData = TRUE; + do { + ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index); + ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError()); + ok(error == SNMP_ERRORSTATUS_NOERROR, + "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); + ok(index == 0, "expected index 0, got %d\n", index); + if (!ret) + moreData = FALSE; + else if (error) + moreData = FALSE; + else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, + vars[0].name.idLength)) + moreData = FALSE; + if (moreData) + { + /* Make sure the size of the OID is right. + * FIXME: don't know if IPv6 addrs are shared with this table. + * Don't think so, but I'm not certain. + */ + ok(vars2[0].name.idLength == vars[0].name.idLength + 4, + "expected length %d, got %d\n", vars[0].name.idLength + 4, + vars2[0].name.idLength); + /* Make sure the type is right */ + ok(vars2[0].value.asnType == ASN_IPADDRESS, + "expected type ASN_IPADDRESS, got %02x\n", + vars2[0].value.asnType); + if (vars2[0].value.asnType == ASN_IPADDRESS) + { + UINT i; + + /* This looks uglier than it is: the base OID for the IP + * address, 1.3.6.1.2.1.4.20.1.1, is appended with the IP + * address of the entry. So e.g. the loopback address is + * identified in MIB2 as 1.3.6.1.2.1.4.20.1.1.127.0.0.1 + */ + for (i = 0; i < vars2[0].value.asnValue.address.length; i++) + { + ok(vars2[0].value.asnValue.address.stream[i] == + vars2[0].name.ids[vars2[0].name.idLength - 4 + i], + "expected ident byte %d to be %d, got %d\n", i, + vars2[0].value.asnValue.address.stream[i], + vars2[0].name.ids[vars2[0].name.idLength - 4 + i]); + } + } + } + } while (moreData); + SnmpUtilVarBindFree(&vars2[0]); + + /* Check the type and OIDs of the IP route table */ + vars[0].name.idLength = DEFINE_SIZEOF(mib2IpRouteTable); + vars[0].name.ids = mib2IpRouteTable; + SnmpUtilOidCpy(&vars2[0].name, &vars[0].name); + vars2[0].value.asnType = 0; + list.len = 1; + list.list = vars2; + moreData = TRUE; + do { + ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index); + ok(ret, "SnmpExtensionQuery failed: %d\n", GetLastError()); + ok(error == SNMP_ERRORSTATUS_NOERROR, + "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error); + ok(index == 0, "expected index 0, got %d\n", index); + if (!ret) + moreData = FALSE; + else if (error) + moreData = FALSE; + else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, + vars[0].name.idLength)) + moreData = FALSE; + if (moreData) + { + /* Make sure the size of the OID is right. + * FIXME: don't know if IPv6 addrs are shared with this table. + * Don't think so, but I'm not certain. + */ + ok(vars2[0].name.idLength = vars[0].name.idLength + 4, + "expected length %d, got %d\n", vars[0].name.idLength + 4, + vars2[0].name.idLength); + /* Make sure the type is right */ + ok(vars2[0].value.asnType == ASN_IPADDRESS, + "expected type ASN_IPADDRESS, got %02x\n", + vars2[0].value.asnType); + if (vars2[0].value.asnType == ASN_IPADDRESS) + { + UINT i; + + /* The base OID for the route table, 1.3.6.1.2.1.4.21.1.1, is + * appended with the dest IP address of the entry. So e.g. a + * route entry for 224.0.0.0 is identified in MIB2 as + * 1.3.6.1.2.1.4.21.1.1.224.0.0.0 + */ + for (i = 0; i < vars2[0].value.asnValue.address.length; i++) + { + ok(vars2[0].value.asnValue.address.stream[i] == + vars2[0].name.ids[vars2[0].name.idLength - 4 + i], + "expected ident byte %d to be %d, got %d\n", i, + vars2[0].value.asnValue.address.stream[i], + vars2[0].name.ids[vars2[0].name.idLength - 4 + i]); + } + } + } + } while (moreData); + SnmpUtilVarBindFree(&vars2[0]); +} + +START_TEST(main) +{ + inetmib1 = LoadLibraryA("inetmib1"); + testInit(); + testQuery(); +} diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c index a7fd40d7bf0..5e40219ccfa 100644 --- a/dlls/iphlpapi/ipstats.c +++ b/dlls/iphlpapi/ipstats.c @@ -28,6 +28,9 @@ #include #include #include +#ifdef HAVE_ALIAS_H +#include +#endif #ifdef HAVE_SYS_SOCKET_H #include #endif @@ -43,28 +46,54 @@ #ifdef HAVE_NET_IF_H #include #endif +#ifdef HAVE_NET_IF_DL_H +#include +#endif +#ifdef HAVE_NET_IF_TYPES_H +#include +#endif #ifdef HAVE_NET_ROUTE_H #include #endif #ifdef HAVE_NET_IF_ARP_H #include #endif +#ifdef HAVE_NETINET_IF_ETHER_H +#include +#endif +#ifdef HAVE_NETINET_IP_H +#include +#endif #ifdef HAVE_NETINET_TCP_H #include #endif #ifdef HAVE_NETINET_TCP_FSM_H #include #endif - #ifdef HAVE_NETINET_IN_PCB_H #include #endif #ifdef HAVE_NETINET_TCP_VAR_H #include #endif +#ifdef HAVE_NETINET_TCP_TIMER_H +#include +#endif +#ifdef HAVE_NETINET_IP_ICMP_H +#include +#endif +#ifdef HAVE_NETINET_ICMP_VAR_H +#include +#endif #ifdef HAVE_NETINET_IP_VAR_H #include #endif +#ifdef HAVE_NETINET_UDP_H +#include +#endif +#ifdef HAVE_NETINET_UDP_VAR_H +#include +#endif #ifdef HAVE_SYS_SYSCTL_H #include @@ -102,15 +131,60 @@ WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi); DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry) { - FILE *fp; - - if (!name) - return ERROR_INVALID_PARAMETER; - if (!entry) +#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_IFLIST) + int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_IFLIST, if_nametoindex(name)}; +#define MIB_LEN (sizeof(mib) / sizeof(mib[0])) + + size_t needed; + char *buf, *end; + struct if_msghdr *ifm; + struct if_data ifdata; + if (!name || !entry) return ERROR_INVALID_PARAMETER; + if(sysctl(mib, MIB_LEN, NULL, &needed, NULL, 0) == -1) + { + ERR ("failed to get size of iflist\n"); + return ERROR_NOT_SUPPORTED; + } + buf = HeapAlloc (GetProcessHeap (), 0, needed); + if (!buf) return ERROR_NOT_SUPPORTED; + if(sysctl(mib, MIB_LEN, buf, &needed, NULL, 0) == -1) + { + ERR ("failed to get iflist\n"); + HeapFree (GetProcessHeap (), 0, buf); + return ERROR_NOT_SUPPORTED; + } + else + for ( end = buf + needed; buf < end; buf += ifm->ifm_msglen) + { + ifm = (struct if_msghdr *) buf; + if(ifm->ifm_type == RTM_IFINFO && ifm->ifm_data.ifi_type == IFT_ETHER) + { + ifdata = ifm->ifm_data; + entry->dwMtu = ifdata.ifi_mtu; + entry->dwSpeed = ifdata.ifi_baudrate; + entry->dwInOctets = ifdata.ifi_ibytes; + entry->dwInErrors = ifdata.ifi_ierrors; + entry->dwInDiscards = ifdata.ifi_iqdrops; + entry->dwInUcastPkts = ifdata.ifi_ipackets; + entry->dwInNUcastPkts = ifdata.ifi_imcasts; + entry->dwOutOctets = ifdata.ifi_obytes; + entry->dwOutUcastPkts = ifdata.ifi_opackets; + entry->dwOutErrors = ifdata.ifi_oerrors; + HeapFree (GetProcessHeap (), 0, buf); + return NO_ERROR; + } + } + HeapFree (GetProcessHeap (), 0, buf); + return ERROR_NOT_SUPPORTED; +#else /* get interface stats from /proc/net/dev, no error if can't no inUnknownProtos, outNUcastPkts, outQLen */ + FILE *fp; + + if (!name || !entry) + return ERROR_INVALID_PARAMETER; fp = fopen("/proc/net/dev", "r"); if (fp) { char buf[512] = { 0 }, *ptr; @@ -188,10 +262,70 @@ DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry) } return NO_ERROR; +#endif } DWORD getICMPStats(MIB_ICMP *stats) { +#if defined(HAVE_SYS_SYSCTL_H) && defined(ICMPCTL_STATS) + int mib[] = {CTL_NET, PF_INET, IPPROTO_ICMP, ICMPCTL_STATS}; +#define MIB_LEN (sizeof(mib) / sizeof(mib[0])) + size_t needed; + struct icmpstat icmp_stat; + int i; + + if (!stats) + return ERROR_INVALID_PARAMETER; + + needed = sizeof(icmp_stat); + if(sysctl(mib, MIB_LEN, &icmp_stat, &needed, NULL, 0) == -1) + { + ERR ("failed to get icmpstat\n"); + return ERROR_NOT_SUPPORTED; + } + + + /*in stats */ + stats->stats.icmpInStats.dwMsgs = icmp_stat.icps_badcode + icmp_stat.icps_checksum + icmp_stat.icps_tooshort + icmp_stat.icps_badlen; + for(i = 0; i <= ICMP_MAXTYPE; i++) + stats->stats.icmpInStats.dwMsgs += icmp_stat.icps_inhist[i]; + + stats->stats.icmpInStats.dwErrors = icmp_stat.icps_badcode + icmp_stat.icps_tooshort + icmp_stat.icps_checksum + icmp_stat.icps_badlen; + + stats->stats.icmpInStats.dwDestUnreachs = icmp_stat.icps_inhist[ICMP_UNREACH]; + stats->stats.icmpInStats.dwTimeExcds = icmp_stat.icps_inhist[ICMP_TIMXCEED]; + stats->stats.icmpInStats.dwParmProbs = icmp_stat.icps_inhist[ICMP_PARAMPROB]; + stats->stats.icmpInStats.dwSrcQuenchs = icmp_stat.icps_inhist[ICMP_SOURCEQUENCH]; + stats->stats.icmpInStats.dwRedirects = icmp_stat.icps_inhist[ICMP_REDIRECT]; + stats->stats.icmpInStats.dwEchos = icmp_stat.icps_inhist[ICMP_ECHO]; + stats->stats.icmpInStats.dwEchoReps = icmp_stat.icps_inhist[ICMP_ECHOREPLY]; + stats->stats.icmpInStats.dwTimestamps = icmp_stat.icps_inhist[ICMP_TSTAMP]; + stats->stats.icmpInStats.dwTimestampReps = icmp_stat.icps_inhist[ICMP_TSTAMPREPLY]; + stats->stats.icmpInStats.dwAddrMasks = icmp_stat.icps_inhist[ICMP_MASKREQ]; + stats->stats.icmpInStats.dwAddrMaskReps = icmp_stat.icps_inhist[ICMP_MASKREPLY]; + + + /* out stats */ + stats->stats.icmpOutStats.dwMsgs = icmp_stat.icps_oldshort + icmp_stat.icps_oldicmp; + for(i = 0; i <= ICMP_MAXTYPE; i++) + stats->stats.icmpOutStats.dwMsgs += icmp_stat.icps_outhist[i]; + + stats->stats.icmpOutStats.dwErrors = icmp_stat.icps_oldshort + icmp_stat.icps_oldicmp; + + stats->stats.icmpOutStats.dwDestUnreachs = icmp_stat.icps_outhist[ICMP_UNREACH]; + stats->stats.icmpOutStats.dwTimeExcds = icmp_stat.icps_outhist[ICMP_TIMXCEED]; + stats->stats.icmpOutStats.dwParmProbs = icmp_stat.icps_outhist[ICMP_PARAMPROB]; + stats->stats.icmpOutStats.dwSrcQuenchs = icmp_stat.icps_outhist[ICMP_SOURCEQUENCH]; + stats->stats.icmpOutStats.dwRedirects = icmp_stat.icps_outhist[ICMP_REDIRECT]; + stats->stats.icmpOutStats.dwEchos = icmp_stat.icps_outhist[ICMP_ECHO]; + stats->stats.icmpOutStats.dwEchoReps = icmp_stat.icps_outhist[ICMP_ECHOREPLY]; + stats->stats.icmpOutStats.dwTimestamps = icmp_stat.icps_outhist[ICMP_TSTAMP]; + stats->stats.icmpOutStats.dwTimestampReps = icmp_stat.icps_outhist[ICMP_TSTAMPREPLY]; + stats->stats.icmpOutStats.dwAddrMasks = icmp_stat.icps_outhist[ICMP_MASKREQ]; + stats->stats.icmpOutStats.dwAddrMaskReps = icmp_stat.icps_outhist[ICMP_MASKREPLY]; + + return NO_ERROR; +#else FILE *fp; if (!stats) @@ -321,10 +455,62 @@ DWORD getICMPStats(MIB_ICMP *stats) } return NO_ERROR; +#endif } DWORD getIPStats(PMIB_IPSTATS stats) { +#if defined(HAVE_SYS_SYSCTL_H) && defined(IPCTL_STATS) + int mib[] = {CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS}; +#define MIB_LEN (sizeof(mib) / sizeof(mib[0])) + int ip_ttl, ip_forwarding; + struct ipstat ip_stat; + size_t needed; + + if (!stats) + return ERROR_INVALID_PARAMETER; + + needed = sizeof(ip_stat); + if(sysctl(mib, MIB_LEN, &ip_stat, &needed, NULL, 0) == -1) + { + ERR ("failed to get ipstat\n"); + return ERROR_NOT_SUPPORTED; + } + + needed = sizeof(ip_ttl); + if (sysctlbyname ("net.inet.ip.ttl", &ip_ttl, &needed, NULL, 0) == -1) + { + ERR ("failed to get ip Default TTL\n"); + return ERROR_NOT_SUPPORTED; + } + + needed = sizeof(ip_forwarding); + if (sysctlbyname ("net.inet.ip.forwarding", &ip_forwarding, &needed, NULL, 0) == -1) + { + ERR ("failed to get ip forwarding\n"); + return ERROR_NOT_SUPPORTED; + } + + stats->dwForwarding = ip_forwarding; + stats->dwDefaultTTL = ip_ttl; + stats->dwInDelivers = ip_stat.ips_delivered; + stats->dwInHdrErrors = ip_stat.ips_badhlen + ip_stat.ips_badsum + ip_stat.ips_tooshort + ip_stat.ips_badlen; + stats->dwInAddrErrors = ip_stat.ips_cantforward; + stats->dwInReceives = ip_stat.ips_total; + stats->dwForwDatagrams = ip_stat.ips_forward; + stats->dwInUnknownProtos = ip_stat.ips_noproto; + stats->dwInDiscards = ip_stat.ips_fragdropped; + stats->dwOutDiscards = ip_stat.ips_odropped; + stats->dwReasmOks = ip_stat.ips_reassembled; + stats->dwFragOks = ip_stat.ips_fragmented; + stats->dwFragFails = ip_stat.ips_cantfrag; + stats->dwReasmTimeout = ip_stat.ips_fragtimeout; + stats->dwOutNoRoutes = ip_stat.ips_noroute; + stats->dwOutRequests = ip_stat.ips_localout; + stats->dwReasmReqds = ip_stat.ips_fragments; + + return NO_ERROR; +#else FILE *fp; if (!stats) @@ -438,10 +624,51 @@ DWORD getIPStats(PMIB_IPSTATS stats) } return NO_ERROR; +#endif } DWORD getTCPStats(MIB_TCPSTATS *stats) { +#if defined(HAVE_SYS_SYSCTL_H) && defined(UDPCTL_STATS) +#ifndef TCPTV_MIN /* got removed in Mac OS X for some reason */ +#define TCPTV_MIN 2 +#define TCPTV_REXMTMAX 128 +#endif + int mib[] = {CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_STATS}; +#define MIB_LEN (sizeof(mib) / sizeof(mib[0])) +#define hz 1000 + struct tcpstat tcp_stat; + size_t needed; + + if (!stats) + return ERROR_INVALID_PARAMETER; + needed = sizeof(tcp_stat); + + if(sysctl(mib, MIB_LEN, &tcp_stat, &needed, NULL, 0) == -1) + { + ERR ("failed to get tcpstat\n"); + return ERROR_NOT_SUPPORTED; + } + + stats->dwRtoAlgorithm = MIB_TCP_RTO_VANJ; + stats->dwRtoMin = TCPTV_MIN; + stats->dwRtoMax = TCPTV_REXMTMAX; + stats->dwMaxConn = -1; + stats->dwActiveOpens = tcp_stat.tcps_connattempt; + stats->dwPassiveOpens = tcp_stat.tcps_accepts; + stats->dwAttemptFails = tcp_stat.tcps_conndrops; + stats->dwEstabResets = tcp_stat.tcps_drops; + stats->dwCurrEstab = 0; + stats->dwInSegs = tcp_stat.tcps_rcvtotal; + stats->dwOutSegs = tcp_stat.tcps_sndtotal - tcp_stat.tcps_sndrexmitpack; + stats->dwRetransSegs = tcp_stat.tcps_sndrexmitpack; + stats->dwInErrs = tcp_stat.tcps_rcvbadsum + tcp_stat.tcps_rcvbadoff + tcp_stat.tcps_rcvmemdrop + tcp_stat.tcps_rcvshort; + stats->dwOutRsts = tcp_stat.tcps_sndctrl - tcp_stat.tcps_closed; + stats->dwNumConns = tcp_stat.tcps_connects; + + return NO_ERROR; + +#else FILE *fp; if (!stats) @@ -475,7 +702,7 @@ DWORD getTCPStats(MIB_TCPSTATS *stats) ptr = endPtr; } if (ptr && *ptr) { - stats->dwRtoMin = strtoul(ptr, &endPtr, 10); + stats->dwRtoMax = strtoul(ptr, &endPtr, 10); ptr = endPtr; } if (ptr && *ptr) { @@ -534,10 +761,35 @@ DWORD getTCPStats(MIB_TCPSTATS *stats) } return NO_ERROR; +#endif } DWORD getUDPStats(MIB_UDPSTATS *stats) { +#if defined(HAVE_SYS_SYSCTL_H) && defined(UDPCTL_STATS) + int mib[] = {CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_STATS}; +#define MIB_LEN (sizeof(mib) / sizeof(mib[0])) + struct udpstat udp_stat; + size_t needed; + if (!stats) + return ERROR_INVALID_PARAMETER; + + needed = sizeof(udp_stat); + + if(sysctl(mib, MIB_LEN, &udp_stat, &needed, NULL, 0) == -1) + { + ERR ("failed to get udpstat\n"); + return ERROR_NOT_SUPPORTED; + } + + stats->dwInDatagrams = udp_stat.udps_ipackets; + stats->dwOutDatagrams = udp_stat.udps_opackets; + stats->dwNoPorts = udp_stat.udps_noport; + stats->dwInErrors = udp_stat.udps_hdrops + udp_stat.udps_badsum + udp_stat.udps_fullsock + udp_stat.udps_badlen; + stats->dwNumAddrs = getNumUdpEntries(); + + return NO_ERROR; +#else FILE *fp; if (!stats) @@ -593,6 +845,7 @@ DWORD getUDPStats(MIB_UDPSTATS *stats) } return NO_ERROR; +#endif } static DWORD getNumWithOneHeader(const char *filename) @@ -863,7 +1116,7 @@ DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap, addr = 0; else if (sa->sa_family != AF_INET) { - ERR ("Received unsupported sockaddr family 0x%x\n", + WARN ("Received unsupported sockaddr family 0x%x\n", sa->sa_family); addr = 0; } @@ -889,7 +1142,7 @@ DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap, break; default: - ERR ("Unexpected address type 0x%x\n", i); + WARN ("Unexpected address type 0x%x\n", i); } } @@ -993,18 +1246,52 @@ DWORD getRouteTable(PMIB_IPFORWARDTABLE *ppIpForwardTable, HANDLE heap, DWORD getNumArpEntries(void) { +#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP) + int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_LLINFO}; +#define MIB_LEN (sizeof(mib) / sizeof(mib[0])) + DWORD arpEntries = 0; + size_t needed; + char *buf, *lim, *next; + struct rt_msghdr *rtm; + struct sockaddr_inarp *sinarp; + struct sockaddr_dl *sdl; + + if (sysctl (mib, MIB_LEN, NULL, &needed, NULL, 0) == -1) + { + ERR ("failed to get size of arp table\n"); + return 0; + } + + buf = HeapAlloc (GetProcessHeap (), 0, needed); + if (!buf) return 0; + + if (sysctl (mib, MIB_LEN, buf, &needed, NULL, 0) == -1) + { + ERR ("failed to get arp table\n"); + HeapFree (GetProcessHeap (), 0, buf); + return 0; + } + + lim = buf + needed; + next = buf; + while(next < lim) + { + rtm = (struct rt_msghdr *)next; + sinarp=(struct sockaddr_inarp *)(rtm + 1); + sdl = (struct sockaddr_dl *)((char *)sinarp + ROUNDUP(sinarp->sin_len)); + if(sdl->sdl_alen) /* arp entry */ + arpEntries++; + next += rtm->rtm_msglen; + } + HeapFree (GetProcessHeap (), 0, buf); + return arpEntries; +#endif return getNumWithOneHeader("/proc/net/arp"); } DWORD getArpTable(PMIB_IPNETTABLE *ppIpNetTable, HANDLE heap, DWORD flags) { - DWORD ret; - -#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP) - ERR ("unimplemented!\n"); - return ERROR_NOT_SUPPORTED; -#endif - + DWORD ret = NO_ERROR; if (!ppIpNetTable) ret = ERROR_INVALID_PARAMETER; else { @@ -1015,10 +1302,76 @@ DWORD getArpTable(PMIB_IPNETTABLE *ppIpNetTable, HANDLE heap, DWORD flags) if (numEntries > 1) size += (numEntries - 1) * sizeof(MIB_IPNETROW); table = HeapAlloc(heap, flags, size); +#if defined(HAVE_SYS_SYSCTL_H) && defined(NET_RT_DUMP) + if (table) + { + int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_LLINFO}; +#define MIB_LEN (sizeof(mib) / sizeof(mib[0])) + size_t needed; + char *buf, *lim, *next; + struct rt_msghdr *rtm; + struct sockaddr_inarp *sinarp; + struct sockaddr_dl *sdl; + + *ppIpNetTable = table; + table->dwNumEntries = 0; + + if (sysctl (mib, MIB_LEN, NULL, &needed, NULL, 0) == -1) + { + ERR ("failed to get size of arp table\n"); + return ERROR_NOT_SUPPORTED; + } + + buf = HeapAlloc (GetProcessHeap (), 0, needed); + if (!buf) return ERROR_OUTOFMEMORY; + + if (sysctl (mib, MIB_LEN, buf, &needed, NULL, 0) == -1) + { + ERR ("failed to get arp table\n"); + HeapFree (GetProcessHeap (), 0, buf); + return ERROR_NOT_SUPPORTED; + } + + lim = buf + needed; + next = buf; + while(next < lim) + { + rtm = (struct rt_msghdr *)next; + sinarp=(struct sockaddr_inarp *)(rtm + 1); + sdl = (struct sockaddr_dl *)((char *)sinarp + ROUNDUP(sinarp->sin_len)); + if(sdl->sdl_alen) /* arp entry */ + { + DWORD byte = strtoul(&sdl->sdl_data[sdl->sdl_alen], NULL, 16); + memset(&table->table[table->dwNumEntries], 0, sizeof(MIB_IPNETROW)); + table->table[table->dwNumEntries].dwAddr = sinarp->sin_addr.s_addr; + table->table[table->dwNumEntries].dwIndex = sdl->sdl_index; + table->table[table->dwNumEntries].dwPhysAddrLen = sdl->sdl_alen; + + table->table[table->dwNumEntries].bPhysAddr[ + table->table[table->dwNumEntries].dwPhysAddrLen++] = + byte & 0x0ff; + if(rtm->rtm_rmx.rmx_expire == 0) + table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_STATIC; + else if(sinarp->sin_other & SIN_PROXY) + table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_OTHER; + else if(rtm->rtm_rmx.rmx_expire != 0) + table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_DYNAMIC; + else + table->table[table->dwNumEntries].dwType = MIB_IPNET_TYPE_INVALID; + + table->dwNumEntries++; + } + next += rtm->rtm_msglen; + } + HeapFree (GetProcessHeap (), 0, buf); + } + else + ret = ERROR_OUTOFMEMORY; + return ret; +#endif + if (table) { FILE *fp; - - ret = NO_ERROR; *ppIpNetTable = table; table->dwNumEntries = 0; /* get from /proc/net/arp, no error if can't */ @@ -1096,7 +1449,11 @@ DWORD getArpTable(PMIB_IPNETTABLE *ppIpNetTable, HANDLE heap, DWORD flags) DWORD getNumUdpEntries(void) { +#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_NETINET_IN_PCB_H) + return getNumWithOneHeader ("net.inet.udp.pcblist"); +#else return getNumWithOneHeader("/proc/net/udp"); +#endif } DWORD getUdpTable(PMIB_UDPTABLE *ppUdpTable, HANDLE heap, DWORD flags) diff --git a/dlls/kernel32/console.c b/dlls/kernel32/console.c index 21ce10af743..a9850606857 100644 --- a/dlls/kernel32/console.c +++ b/dlls/kernel32/console.c @@ -2239,7 +2239,15 @@ BOOL WINAPI GetConsoleCursorInfo(HANDLE hCon, LPCONSOLE_CURSOR_INFO cinfo) } SERVER_END_REQ; - TRACE("(%p) returning (%d,%d)\n", hCon, cinfo->dwSize, cinfo->bVisible); + if (!ret) return FALSE; + + if (!cinfo) + { + SetLastError(ERROR_INVALID_ACCESS); + ret = FALSE; + } + else TRACE("(%p) returning (%d,%d)\n", hCon, cinfo->dwSize, cinfo->bVisible); + return ret; } @@ -2536,6 +2544,33 @@ BOOL WINAPI AttachConsole(DWORD dwProcessId) return TRUE; } +/****************************************************************** + * GetConsoleDisplayMode (KERNEL32.@) + */ +BOOL WINAPI GetConsoleDisplayMode(LPDWORD lpModeFlags) +{ + TRACE("semi-stub: %p\n", lpModeFlags); + /* It is safe to successfully report windowed mode */ + *lpModeFlags = 0; + return TRUE; +} + +/****************************************************************** + * SetConsoleDisplayMode (KERNEL32.@) + */ +BOOL WINAPI SetConsoleDisplayMode(HANDLE hConsoleOutput, DWORD dwFlags, + COORD *lpNewScreenBufferDimensions) +{ + TRACE("(%p, %x, (%d, %d))\n", hConsoleOutput, dwFlags, + lpNewScreenBufferDimensions->X, lpNewScreenBufferDimensions->Y); + if (dwFlags == 1) + { + /* We cannot switch to fullscreen */ + return FALSE; + } + return TRUE; +} + /* ==================================================================== * diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 1a18899d6c3..6a24e333fc2 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -457,7 +457,7 @@ @ stub GetConsoleCommandHistoryW @ stdcall GetConsoleCursorInfo(long ptr) @ stub GetConsoleCursorMode -@ stub GetConsoleDisplayMode +@ stdcall GetConsoleDisplayMode(ptr) @ stub GetConsoleFontInfo @ stub GetConsoleFontSize @ stub GetConsoleHardwareState @@ -712,6 +712,7 @@ @ stdcall InitAtomTable(long) @ stdcall InitializeCriticalSection(ptr) @ stdcall InitializeCriticalSectionAndSpinCount(ptr long) +@ stdcall InitializeCriticalSectionEx(ptr long long) @ stdcall InitializeSListHead(ptr) ntdll.RtlInitializeSListHead @ stdcall InterlockedCompareExchange (ptr long long) @ stdcall InterlockedDecrement(ptr) @@ -963,7 +964,7 @@ @ stdcall SetConsoleCursorInfo(long ptr) @ stub SetConsoleCursorMode @ stdcall SetConsoleCursorPosition(long long) -@ stub SetConsoleDisplayMode +@ stdcall SetConsoleDisplayMode(long long ptr) @ stub SetConsoleFont @ stub SetConsoleHardwareState @ stub SetConsoleIcon diff --git a/dlls/kernel32/nls/afk.nls b/dlls/kernel32/nls/afk.nls index 4b59b01e5dd..32cb571a2a0 100644 --- a/dlls/kernel32/nls/afk.nls +++ b/dlls/kernel32/nls/afk.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_AFRIKAANS, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Afrikaans" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "yyyy/MM/dd" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/ara.nls b/dlls/kernel32/nls/ara.nls index 878eec6c1b1..0f131cc8fb0 100644 --- a/dlls/kernel32/nls/ara.nls +++ b/dlls/kernel32/nls/ara.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/arb.nls b/dlls/kernel32/nls/arb.nls index cc700f52d77..7a413a15ecd 100644 --- a/dlls/kernel32/nls/arb.nls +++ b/dlls/kernel32/nls/arb.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_LEBANON LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/are.nls b/dlls/kernel32/nls/are.nls index ce11d5b9405..1678e93b0dc 100644 --- a/dlls/kernel32/nls/are.nls +++ b/dlls/kernel32/nls/are.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_EGYPT LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/arg.nls b/dlls/kernel32/nls/arg.nls index 13cfcadaa7a..c15a30ac766 100644 --- a/dlls/kernel32/nls/arg.nls +++ b/dlls/kernel32/nls/arg.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_ALGERIA LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd-MM-yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/arh.nls b/dlls/kernel32/nls/arh.nls index f7c7f245993..62ba4e4475d 100644 --- a/dlls/kernel32/nls/arh.nls +++ b/dlls/kernel32/nls/arh.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_BAHRAIN LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/ari.nls b/dlls/kernel32/nls/ari.nls index fd2bc49752e..e1d47740c22 100644 --- a/dlls/kernel32/nls/ari.nls +++ b/dlls/kernel32/nls/ari.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_IRAQ LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/arj.nls b/dlls/kernel32/nls/arj.nls index b96583885cf..951d913c93d 100644 --- a/dlls/kernel32/nls/arj.nls +++ b/dlls/kernel32/nls/arj.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_JORDAN LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/ark.nls b/dlls/kernel32/nls/ark.nls index 69fba0d05ba..aa2486d2ea1 100644 --- a/dlls/kernel32/nls/ark.nls +++ b/dlls/kernel32/nls/ark.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_KUWAIT LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/arl.nls b/dlls/kernel32/nls/arl.nls index 6a5eb9d36a8..cbafbe04aeb 100644 --- a/dlls/kernel32/nls/arl.nls +++ b/dlls/kernel32/nls/arl.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_LIBYA LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/arm.nls b/dlls/kernel32/nls/arm.nls index 1865376e81a..1f7dfa7ccc9 100644 --- a/dlls/kernel32/nls/arm.nls +++ b/dlls/kernel32/nls/arm.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_MOROCCO LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd-MM-yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/aro.nls b/dlls/kernel32/nls/aro.nls index bc50a9a1d35..6a5f705092f 100644 --- a/dlls/kernel32/nls/aro.nls +++ b/dlls/kernel32/nls/aro.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_OMAN LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/arq.nls b/dlls/kernel32/nls/arq.nls index 2648558a913..328f8160b6e 100644 --- a/dlls/kernel32/nls/arq.nls +++ b/dlls/kernel32/nls/arq.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_QATAR LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/ars.nls b/dlls/kernel32/nls/ars.nls index b07620665cd..5f4b57e116b 100644 --- a/dlls/kernel32/nls/ars.nls +++ b/dlls/kernel32/nls/ars.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_SYRIA LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/art.nls b/dlls/kernel32/nls/art.nls index e4a370f2a15..8f400de15ae 100644 --- a/dlls/kernel32/nls/art.nls +++ b/dlls/kernel32/nls/art.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_TUNISIA LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd-MM-yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/aru.nls b/dlls/kernel32/nls/aru.nls index 9b8e86444cc..c058f1b8dee 100644 --- a/dlls/kernel32/nls/aru.nls +++ b/dlls/kernel32/nls/aru.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_UAE LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/ary.nls b/dlls/kernel32/nls/ary.nls index c8f826d3723..fbc3adfcb42 100644 --- a/dlls/kernel32/nls/ary.nls +++ b/dlls/kernel32/nls/ary.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARABIC, SUBLANG_ARABIC_YEMEN LOCALE_SNATIVELANGNAME "ÇáÚÑÈíÉ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/aze.nls b/dlls/kernel32/nls/aze.nls index 283207943e9..8cd71fd5c9d 100644 --- a/dlls/kernel32/nls/aze.nls +++ b/dlls/kernel32/nls/aze.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_AZERI, SUBLANG_AZERI_CYRILLIC LOCALE_SNATIVELANGNAME L"\x0410\x0437\x04d9\x0440\x0431\x0430\x0458\x04b9\x0430\x043d" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/azl.nls b/dlls/kernel32/nls/azl.nls index 553abefa7f2..6242addb581 100644 --- a/dlls/kernel32/nls/azl.nls +++ b/dlls/kernel32/nls/azl.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_AZERI, SUBLANG_AZERI_LATIN LOCALE_SNATIVELANGNAME L"Az\x0259rbaycan\x00ad\x0131l\x0131" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/bel.nls b/dlls/kernel32/nls/bel.nls index 6bd26c90662..5f39c9133ce 100644 --- a/dlls/kernel32/nls/bel.nls +++ b/dlls/kernel32/nls/bel.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_BELARUSIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Áåëàðóñêàÿ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Cyrl;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/bgr.nls b/dlls/kernel32/nls/bgr.nls index a8d997c3afb..18a350a01d1 100644 --- a/dlls/kernel32/nls/bgr.nls +++ b/dlls/kernel32/nls/bgr.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "áúëãàðñêè" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Cyrl;" LOCALE_SSHORTDATE "dd.M.yyyy 'ã.'" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/brf.nls b/dlls/kernel32/nls/brf.nls index 820caa0cfad..8c0953c4065 100644 --- a/dlls/kernel32/nls/brf.nls +++ b/dlls/kernel32/nls/brf.nls @@ -129,6 +129,7 @@ STRINGTABLE LANGUAGE LANG_BRETON, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Brezhoneg" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/cat.nls b/dlls/kernel32/nls/cat.nls index f2d2e75e861..75cca9f4b5e 100644 --- a/dlls/kernel32/nls/cat.nls +++ b/dlls/kernel32/nls/cat.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_CATALAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "català" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/chs.nls b/dlls/kernel32/nls/chs.nls index 692c5e5d61e..c3e7bf8490c 100644 --- a/dlls/kernel32/nls/chs.nls +++ b/dlls/kernel32/nls/chs.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED LOCALE_SNATIVELANGNAME "ÖÐÎÄ(¼òÌå)" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Hans;" LOCALE_SSHORTDATE "yyyy-M-d" LOCALE_SSORTNAME "Pronunciation" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/cht.nls b/dlls/kernel32/nls/cht.nls index 4fb7feac519..7b6edbe8b97 100644 --- a/dlls/kernel32/nls/cht.nls +++ b/dlls/kernel32/nls/cht.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL LOCALE_SNATIVELANGNAME "¤¤¤å(ÁcÅé)" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Hant;" LOCALE_SSHORTDATE "yyyy/M/d" LOCALE_SSORTNAME "Stroke Count" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/cor.nls b/dlls/kernel32/nls/cor.nls index 668e9d43b02..177bc7a91fb 100644 --- a/dlls/kernel32/nls/cor.nls +++ b/dlls/kernel32/nls/cor.nls @@ -129,6 +129,7 @@ STRINGTABLE LANGUAGE LANG_CORNISH, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Kernewek" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/csy.nls b/dlls/kernel32/nls/csy.nls index f73859e1c92..4b99d9f6cac 100644 --- a/dlls/kernel32/nls/csy.nls +++ b/dlls/kernel32/nls/csy.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_CZECH, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "èeština" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d.M.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/cym.nls b/dlls/kernel32/nls/cym.nls index b25c42b1cd2..ff5dbde6152 100644 --- a/dlls/kernel32/nls/cym.nls +++ b/dlls/kernel32/nls/cym.nls @@ -129,6 +129,7 @@ STRINGTABLE LANGUAGE LANG_WELSH, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Cymraeg" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/dan.nls b/dlls/kernel32/nls/dan.nls index 5e6d1fbf186..6f41a9e11be 100644 --- a/dlls/kernel32/nls/dan.nls +++ b/dlls/kernel32/nls/dan.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_DANISH, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "dansk" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd-MM-yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/dea.nls b/dlls/kernel32/nls/dea.nls index 492ff5a8c6f..39d6b80c96e 100644 --- a/dlls/kernel32/nls/dea.nls +++ b/dlls/kernel32/nls/dea.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN LOCALE_SNATIVELANGNAME "Deutsch" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/dec.nls b/dlls/kernel32/nls/dec.nls index 16202f4d691..0badeeb9536 100644 --- a/dlls/kernel32/nls/dec.nls +++ b/dlls/kernel32/nls/dec.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_LIECHTENSTEIN LOCALE_SNATIVELANGNAME "Deutsch" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "'" diff --git a/dlls/kernel32/nls/del.nls b/dlls/kernel32/nls/del.nls index c5af8a40c87..a848e0c2737 100644 --- a/dlls/kernel32/nls/del.nls +++ b/dlls/kernel32/nls/del.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_LUXEMBOURG LOCALE_SNATIVELANGNAME "Deutsch" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/des.nls b/dlls/kernel32/nls/des.nls index 34ea893f4d4..bdee8763e64 100644 --- a/dlls/kernel32/nls/des.nls +++ b/dlls/kernel32/nls/des.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_SWISS LOCALE_SNATIVELANGNAME "Deutsch" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "'" diff --git a/dlls/kernel32/nls/deu.nls b/dlls/kernel32/nls/deu.nls index 73803a89440..4e392334a83 100644 --- a/dlls/kernel32/nls/deu.nls +++ b/dlls/kernel32/nls/deu.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_GERMAN, SUBLANG_GERMAN LOCALE_SNATIVELANGNAME "Deutsch" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Dictionary" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/div.nls b/dlls/kernel32/nls/div.nls index 2ade0fba62a..2383d4004a3 100644 --- a/dlls/kernel32/nls/div.nls +++ b/dlls/kernel32/nls/div.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_DIVEHI, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x078b\x07a8\x0788\x07ac\x0780\x07a8\x0784\x07a6\x0790\x07b0" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Thaa;" LOCALE_SSHORTDATE L"dd/MM/yy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/ell.nls b/dlls/kernel32/nls/ell.nls index 4d3726ccead..c1a4f1e5ba5 100644 --- a/dlls/kernel32/nls/ell.nls +++ b/dlls/kernel32/nls/ell.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_GREEK, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "åëëçíéêÜ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Grek;" LOCALE_SSHORTDATE "d/M/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/ena.nls b/dlls/kernel32/nls/ena.nls index 9a9a1217736..a9d08c8b161 100644 --- a/dlls/kernel32/nls/ena.nls +++ b/dlls/kernel32/nls/ena.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/enb.nls b/dlls/kernel32/nls/enb.nls index f977ff27ca9..dfb8be83591 100644 --- a/dlls/kernel32/nls/enb.nls +++ b/dlls/kernel32/nls/enb.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_CARIBBEAN LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "MM/dd/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/enc.nls b/dlls/kernel32/nls/enc.nls index 153f39f06e0..09fee476fe8 100644 --- a/dlls/kernel32/nls/enc.nls +++ b/dlls/kernel32/nls/enc.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_CAN LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/eng.nls b/dlls/kernel32/nls/eng.nls index 05f21c303b4..0a8f26fd25c 100644 --- a/dlls/kernel32/nls/eng.nls +++ b/dlls/kernel32/nls/eng.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/eni.nls b/dlls/kernel32/nls/eni.nls index b0f7e86dc58..d86e35c783c 100644 --- a/dlls/kernel32/nls/eni.nls +++ b/dlls/kernel32/nls/eni.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_EIRE LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/enj.nls b/dlls/kernel32/nls/enj.nls index e9d7c000383..e1e82599bdd 100644 --- a/dlls/kernel32/nls/enj.nls +++ b/dlls/kernel32/nls/enj.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_JAMAICA LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/enl.nls b/dlls/kernel32/nls/enl.nls index cc9a67b6d76..c8c69a0b74a 100644 --- a/dlls/kernel32/nls/enl.nls +++ b/dlls/kernel32/nls/enl.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_BELIZE LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/enp.nls b/dlls/kernel32/nls/enp.nls index 789cc796ce8..46aa4a2df03 100644 --- a/dlls/kernel32/nls/enp.nls +++ b/dlls/kernel32/nls/enp.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_PHILIPPINES LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "M/d/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/ens.nls b/dlls/kernel32/nls/ens.nls index 67c19d88030..76d02d796e9 100644 --- a/dlls/kernel32/nls/ens.nls +++ b/dlls/kernel32/nls/ens.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_SOUTH_AFRICA LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "yyyy/MM/dd" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/ent.nls b/dlls/kernel32/nls/ent.nls index 37f2de35789..1d1eff7bd5a 100644 --- a/dlls/kernel32/nls/ent.nls +++ b/dlls/kernel32/nls/ent.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_TRINIDAD LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/enu.nls b/dlls/kernel32/nls/enu.nls index 13dfbaffdbd..06322c0f75b 100644 --- a/dlls/kernel32/nls/enu.nls +++ b/dlls/kernel32/nls/enu.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "M/d/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/enw.nls b/dlls/kernel32/nls/enw.nls index f7f51b0e44a..b554462f0fd 100644 --- a/dlls/kernel32/nls/enw.nls +++ b/dlls/kernel32/nls/enw.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_ZIMBABWE LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "M/d/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/enz.nls b/dlls/kernel32/nls/enz.nls index b2e5ebd67f6..1d511437510 100644 --- a/dlls/kernel32/nls/enz.nls +++ b/dlls/kernel32/nls/enz.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_NZ LOCALE_SNATIVELANGNAME "English" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/eox.nls b/dlls/kernel32/nls/eox.nls index 4b263d834b8..f02cd093557 100644 --- a/dlls/kernel32/nls/eox.nls +++ b/dlls/kernel32/nls/eox.nls @@ -37,14 +37,15 @@ STRINGTABLE LANGUAGE LANG_ESPERANTO, SUBLANG_DEFAULT { - LOCALE_FONTSIGNATURE L"" + /* FIXME: .NET 2.0 requires a font signature - English (US) signature added */ + LOCALE_FONTSIGNATURE L"\x00af\x8000\x38cb\x0000\x0000\x0000\x0000\x0000\x0001\x0000\x0000\x8000\x01ff\x003f\x8000\xffff" LOCALE_ICALENDARTYPE L"1" LOCALE_ICENTURY L"0" - LOCALE_ICOUNTRY L"" + LOCALE_ICOUNTRY L"0" LOCALE_ICURRDIGITS L"2" LOCALE_ICURRENCY L"3" LOCALE_IDATE L"1" - LOCALE_IDAYLZERO L"" + LOCALE_IDAYLZERO L"0" LOCALE_IDEFAULTANSICODEPAGE L"0" LOCALE_IDEFAULTCODEPAGE L"1" LOCALE_IDEFAULTCOUNTRY L"" @@ -113,15 +114,15 @@ STRINGTABLE LANGUAGE LANG_ESPERANTO, SUBLANG_DEFAULT LOCALE_SENGCOUNTRY L"" LOCALE_SENGCURRNAME L"Euro" LOCALE_SENGLANGUAGE L"Esperanto" - LOCALE_SGROUPING L"0;0" - LOCALE_SINTLSYMBOL L"EMU" + LOCALE_SGROUPING L"3;0" + LOCALE_SINTLSYMBOL L"EUR" LOCALE_SISO3166CTRYNAME L"" LOCALE_SISO639LANGNAME L"eo" LOCALE_SLANGUAGE L"Esperanto" LOCALE_SLIST L";" LOCALE_SLONGDATE L"ddd, d. MMMM yyyy" LOCALE_SMONDECIMALSEP L"," - LOCALE_SMONGROUPING L"" + LOCALE_SMONGROUPING L"3;0" LOCALE_SMONTHNAME1 L"januaro" LOCALE_SMONTHNAME2 L"februaro" LOCALE_SMONTHNAME3 L"marto" @@ -143,6 +144,7 @@ STRINGTABLE LANGUAGE LANG_ESPERANTO, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"Esperanto" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Latn;" LOCALE_SSHORTDATE L"yyyy-mm-dd" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"." diff --git a/dlls/kernel32/nls/esa.nls b/dlls/kernel32/nls/esa.nls index eafdd3dfed9..b27bb4ee28e 100644 --- a/dlls/kernel32/nls/esa.nls +++ b/dlls/kernel32/nls/esa.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_PANAMA LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "MM/dd/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/esb.nls b/dlls/kernel32/nls/esb.nls index 464ab46452b..90e1a106e56 100644 --- a/dlls/kernel32/nls/esb.nls +++ b/dlls/kernel32/nls/esb.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_BOLIVIA LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/esc.nls b/dlls/kernel32/nls/esc.nls index e838af224d2..c26be6e0c93 100644 --- a/dlls/kernel32/nls/esc.nls +++ b/dlls/kernel32/nls/esc.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_COSTA_RICA LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/esd.nls b/dlls/kernel32/nls/esd.nls index 710865ae512..f424770356a 100644 --- a/dlls/kernel32/nls/esd.nls +++ b/dlls/kernel32/nls/esd.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_DOMINICAN_REPUBLIC LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/ese.nls b/dlls/kernel32/nls/ese.nls index 846009a333e..d8296229221 100644 --- a/dlls/kernel32/nls/ese.nls +++ b/dlls/kernel32/nls/ese.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_EL_SALVADOR LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/esf.nls b/dlls/kernel32/nls/esf.nls index 18e6421b8d5..c62cab4a138 100644 --- a/dlls/kernel32/nls/esf.nls +++ b/dlls/kernel32/nls/esf.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ECUADOR LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/esg.nls b/dlls/kernel32/nls/esg.nls index 4fb0db58c68..2ebc5da9b31 100644 --- a/dlls/kernel32/nls/esg.nls +++ b/dlls/kernel32/nls/esg.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_GUATEMALA LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/esh.nls b/dlls/kernel32/nls/esh.nls index c00a86f6558..606626aa3f5 100644 --- a/dlls/kernel32/nls/esh.nls +++ b/dlls/kernel32/nls/esh.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_HONDURAS LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/esi.nls b/dlls/kernel32/nls/esi.nls index 0787b304759..e90db977b19 100644 --- a/dlls/kernel32/nls/esi.nls +++ b/dlls/kernel32/nls/esi.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_NICARAGUA LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/esl.nls b/dlls/kernel32/nls/esl.nls index 2e19d2174be..869194a9887 100644 --- a/dlls/kernel32/nls/esl.nls +++ b/dlls/kernel32/nls/esl.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_CHILE LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd-MM-yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/esm.nls b/dlls/kernel32/nls/esm.nls index 31cfd79da73..dcfead8ff26 100644 --- a/dlls/kernel32/nls/esm.nls +++ b/dlls/kernel32/nls/esm.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MEXICAN LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/esn.nls b/dlls/kernel32/nls/esn.nls index 22e46daa04c..38885ee2cbc 100644 --- a/dlls/kernel32/nls/esn.nls +++ b/dlls/kernel32/nls/esn.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN LOCALE_SNATIVELANGNAME "español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "International" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/eso.nls b/dlls/kernel32/nls/eso.nls index bf138178479..6b0b54159bd 100644 --- a/dlls/kernel32/nls/eso.nls +++ b/dlls/kernel32/nls/eso.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_COLOMBIA LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/esp.nls b/dlls/kernel32/nls/esp.nls index b28597c358b..68aafc386b6 100644 --- a/dlls/kernel32/nls/esp.nls +++ b/dlls/kernel32/nls/esp.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH LOCALE_SNATIVELANGNAME "español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Traditional" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/esr.nls b/dlls/kernel32/nls/esr.nls index f379ccb1a8d..06e431d0b0a 100644 --- a/dlls/kernel32/nls/esr.nls +++ b/dlls/kernel32/nls/esr.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_PERU LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/ess.nls b/dlls/kernel32/nls/ess.nls index eece7926ce0..79e4d7fe0aa 100644 --- a/dlls/kernel32/nls/ess.nls +++ b/dlls/kernel32/nls/ess.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/esu.nls b/dlls/kernel32/nls/esu.nls index f8e5b207e60..87f1de4a705 100644 --- a/dlls/kernel32/nls/esu.nls +++ b/dlls/kernel32/nls/esu.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_PUERTO_RICO LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/esv.nls b/dlls/kernel32/nls/esv.nls index 5b956079e05..09c77cab9ad 100644 --- a/dlls/kernel32/nls/esv.nls +++ b/dlls/kernel32/nls/esv.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_VENEZUELA LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/esy.nls b/dlls/kernel32/nls/esy.nls index e8efc808e67..b74495358b9 100644 --- a/dlls/kernel32/nls/esy.nls +++ b/dlls/kernel32/nls/esy.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_URUGUAY LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/esz.nls b/dlls/kernel32/nls/esz.nls index 1e3c109482e..35755a38625 100644 --- a/dlls/kernel32/nls/esz.nls +++ b/dlls/kernel32/nls/esz.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_PARAGUAY LOCALE_SNATIVELANGNAME "Español" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/eti.nls b/dlls/kernel32/nls/eti.nls index 7bf858abe44..d6940abfdfd 100644 --- a/dlls/kernel32/nls/eti.nls +++ b/dlls/kernel32/nls/eti.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ESTONIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "eesti" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/euq.nls b/dlls/kernel32/nls/euq.nls index cb751def860..05b42bfbd20 100644 --- a/dlls/kernel32/nls/euq.nls +++ b/dlls/kernel32/nls/euq.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_BASQUE, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "euskara" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "yyyy/MM/dd" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/far.nls b/dlls/kernel32/nls/far.nls index 25ea4a96f44..85c1974a9d4 100644 --- a/dlls/kernel32/nls/far.nls +++ b/dlls/kernel32/nls/far.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_FARSI, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "ÝÇÑÓì" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "yyyy/MM/dd" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/fin.nls b/dlls/kernel32/nls/fin.nls index 894bb9424e4..88725e89c3a 100644 --- a/dlls/kernel32/nls/fin.nls +++ b/dlls/kernel32/nls/fin.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_FINNISH, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "suomi" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d.M.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/fos.nls b/dlls/kernel32/nls/fos.nls index 1dd96bafe7e..b4974b4a4e6 100644 --- a/dlls/kernel32/nls/fos.nls +++ b/dlls/kernel32/nls/fos.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_FAEROESE, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "føroyskt" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd-MM-yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/fra.nls b/dlls/kernel32/nls/fra.nls index cf0d8d0ba21..80b34fb833c 100644 --- a/dlls/kernel32/nls/fra.nls +++ b/dlls/kernel32/nls/fra.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_FRENCH, SUBLANG_FRENCH LOCALE_SNATIVELANGNAME "français" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/frb.nls b/dlls/kernel32/nls/frb.nls index 80a9159f736..caeaa763707 100644 --- a/dlls/kernel32/nls/frb.nls +++ b/dlls/kernel32/nls/frb.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_BELGIAN LOCALE_SNATIVELANGNAME "français" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/frc.nls b/dlls/kernel32/nls/frc.nls index 76909a689f9..5b7730cda07 100644 --- a/dlls/kernel32/nls/frc.nls +++ b/dlls/kernel32/nls/frc.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_CANADIAN LOCALE_SNATIVELANGNAME "français" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "yyyy-MM-dd" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/frl.nls b/dlls/kernel32/nls/frl.nls index 3213cd295c6..e0610e21e3b 100644 --- a/dlls/kernel32/nls/frl.nls +++ b/dlls/kernel32/nls/frl.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_LUXEMBOURG LOCALE_SNATIVELANGNAME "français" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/frm.nls b/dlls/kernel32/nls/frm.nls index 27512307176..511bb510295 100644 --- a/dlls/kernel32/nls/frm.nls +++ b/dlls/kernel32/nls/frm.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_MONACO LOCALE_SNATIVELANGNAME "français" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/frs.nls b/dlls/kernel32/nls/frs.nls index 891e9ee84b0..45f48948294 100644 --- a/dlls/kernel32/nls/frs.nls +++ b/dlls/kernel32/nls/frs.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_FRENCH, SUBLANG_FRENCH_SWISS LOCALE_SNATIVELANGNAME "français" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "'" diff --git a/dlls/kernel32/nls/gae.nls b/dlls/kernel32/nls/gae.nls index c57c4d0705b..6e19ff41674 100644 --- a/dlls/kernel32/nls/gae.nls +++ b/dlls/kernel32/nls/gae.nls @@ -129,6 +129,7 @@ STRINGTABLE LANGUAGE LANG_GAELIC, SUBLANG_GAELIC LOCALE_SNATIVELANGNAME "Gaeilge" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d/M/yy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/gdh.nls b/dlls/kernel32/nls/gdh.nls index 28e3a1b3fad..55480a31218 100644 --- a/dlls/kernel32/nls/gdh.nls +++ b/dlls/kernel32/nls/gdh.nls @@ -129,6 +129,7 @@ STRINGTABLE LANGUAGE LANG_GAELIC, SUBLANG_GAELIC_SCOTTISH LOCALE_SNATIVELANGNAME "Gaidhlig" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/gdv.nls b/dlls/kernel32/nls/gdv.nls index df041db6ef8..67961ce7413 100644 --- a/dlls/kernel32/nls/gdv.nls +++ b/dlls/kernel32/nls/gdv.nls @@ -129,6 +129,7 @@ STRINGTABLE LANGUAGE LANG_GAELIC, SUBLANG_GAELIC_MANX LOCALE_SNATIVELANGNAME "Gaelg" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/glc.nls b/dlls/kernel32/nls/glc.nls index 5f6d146c0bb..16a845de46f 100644 --- a/dlls/kernel32/nls/glc.nls +++ b/dlls/kernel32/nls/glc.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_GALICIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "galego" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/guj.nls b/dlls/kernel32/nls/guj.nls index 211fa31dc31..92c7ac6ed83 100644 --- a/dlls/kernel32/nls/guj.nls +++ b/dlls/kernel32/nls/guj.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_GUJARATI, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x0a97\x0ac1\x0a9c\x0ab0\x0abe\x0aa4\x0ac0" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Gujr;" LOCALE_SSHORTDATE L"dd-MM-yy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/heb.nls b/dlls/kernel32/nls/heb.nls index 19a059289be..23cd711e1c0 100644 --- a/dlls/kernel32/nls/heb.nls +++ b/dlls/kernel32/nls/heb.nls @@ -129,6 +129,7 @@ STRINGTABLE LANGUAGE LANG_HEBREW, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "òáøéú" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Hebr;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/hin.nls b/dlls/kernel32/nls/hin.nls index ca0bbd59db5..b336b3c080f 100644 --- a/dlls/kernel32/nls/hin.nls +++ b/dlls/kernel32/nls/hin.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_HINDI, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x0939\x093f\x0902\x0926\x0940" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Deva;" LOCALE_SSHORTDATE L"dd-MM-yyyy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/hrv.nls b/dlls/kernel32/nls/hrv.nls index 9269e3ce3de..78a83663e77 100644 --- a/dlls/kernel32/nls/hrv.nls +++ b/dlls/kernel32/nls/hrv.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SERBIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "hrvatski" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d.M.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/hun.nls b/dlls/kernel32/nls/hun.nls index aaa7cd1836e..f6a00c719d3 100644 --- a/dlls/kernel32/nls/hun.nls +++ b/dlls/kernel32/nls/hun.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Magyar" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "yyyy. MM. dd." LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/hye.nls b/dlls/kernel32/nls/hye.nls index 2620bc17225..e175fde5fad 100644 --- a/dlls/kernel32/nls/hye.nls +++ b/dlls/kernel32/nls/hye.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ARMENIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x0540\x0561\x0575\x0565\x0580\x0565\x0576" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Armn;" LOCALE_SSHORTDATE L"dd.MM.yyyy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/ind.nls b/dlls/kernel32/nls/ind.nls index 382420d6f5f..f929e27c2b5 100644 --- a/dlls/kernel32/nls/ind.nls +++ b/dlls/kernel32/nls/ind.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_INDONESIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Bahasa Indonesia" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/isl.nls b/dlls/kernel32/nls/isl.nls index 8ab5a9f418b..055068ff3a6 100644 --- a/dlls/kernel32/nls/isl.nls +++ b/dlls/kernel32/nls/isl.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ICELANDIC, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "íslenska" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d.M.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/ita.nls b/dlls/kernel32/nls/ita.nls index 4d8ffb19a03..6fb4fc45e15 100644 --- a/dlls/kernel32/nls/ita.nls +++ b/dlls/kernel32/nls/ita.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN LOCALE_SNATIVELANGNAME "italiano" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/its.nls b/dlls/kernel32/nls/its.nls index 515966b659c..0f6f3f142a4 100644 --- a/dlls/kernel32/nls/its.nls +++ b/dlls/kernel32/nls/its.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN_SWISS LOCALE_SNATIVELANGNAME "italiano" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "'" diff --git a/dlls/kernel32/nls/jpn.nls b/dlls/kernel32/nls/jpn.nls index 8315d3529f6..c2eb795a6e3 100644 --- a/dlls/kernel32/nls/jpn.nls +++ b/dlls/kernel32/nls/jpn.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "“ú–{Œê" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Hani;Hira;Kana;" LOCALE_SSHORTDATE "yyyy/MM/dd" LOCALE_SSORTNAME "XJIS" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/kan.nls b/dlls/kernel32/nls/kan.nls index b7aa6e1025d..dc58af47b8c 100644 --- a/dlls/kernel32/nls/kan.nls +++ b/dlls/kernel32/nls/kan.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_KANNADA, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x0c95\x0ca8\x0ccd\x0ca8\x0ca1" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Knda;" LOCALE_SSHORTDATE L"dd-MM-yy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/kat.nls b/dlls/kernel32/nls/kat.nls index 1761f538c79..52002fa75ca 100644 --- a/dlls/kernel32/nls/kat.nls +++ b/dlls/kernel32/nls/kat.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_GEORGIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x10e5\x10d0\x10e0\x10d7\x10e3\x10da\x10d8" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Geor;" LOCALE_SSHORTDATE L"dd.MM.yyyy" LOCALE_SSORTNAME L"Traditional" LOCALE_STHOUSAND L"\x00a0" diff --git a/dlls/kernel32/nls/kkz.nls b/dlls/kernel32/nls/kkz.nls index 715ef35eb98..929ebfe91b3 100644 --- a/dlls/kernel32/nls/kkz.nls +++ b/dlls/kernel32/nls/kkz.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_KAZAK, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x049a\x0430\x0437\x0430\x049b" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Cyrl;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/knk.nls b/dlls/kernel32/nls/knk.nls index cc0f7becd2f..02c564c7466 100644 --- a/dlls/kernel32/nls/knk.nls +++ b/dlls/kernel32/nls/knk.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_KONKANI, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x0915\x094b\x0902\x0915\x0923\x0940" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Deva;" LOCALE_SSHORTDATE L"dd-MM-yyyy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/kor.nls b/dlls/kernel32/nls/kor.nls index 3aa7ac73d99..c3ea67b6cd2 100644 --- a/dlls/kernel32/nls/kor.nls +++ b/dlls/kernel32/nls/kor.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_KOREAN, SUBLANG_KOREAN LOCALE_SNATIVELANGNAME "Çѱ¹¾î" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Hang;Hani;" LOCALE_SSHORTDATE "yyyy-MM-dd" LOCALE_SSORTNAME "Dictionary" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/kyr.nls b/dlls/kernel32/nls/kyr.nls index 86941152ec7..e720a886012 100644 --- a/dlls/kernel32/nls/kyr.nls +++ b/dlls/kernel32/nls/kyr.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_KYRGYZ, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Êûðãûç" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Cyrl;" LOCALE_SSHORTDATE "dd.MM.yy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/lth.nls b/dlls/kernel32/nls/lth.nls index c1af6fd8673..9674e85f164 100644 --- a/dlls/kernel32/nls/lth.nls +++ b/dlls/kernel32/nls/lth.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_LITHUANIAN, SUBLANG_LITHUANIAN LOCALE_SNATIVELANGNAME "lietuviø" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "yyyy.MM.dd" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/lvi.nls b/dlls/kernel32/nls/lvi.nls index 11faca7bb33..99ee7f1f79b 100644 --- a/dlls/kernel32/nls/lvi.nls +++ b/dlls/kernel32/nls/lvi.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_LATVIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "latvieðu" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "yyyy.MM.dd." LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/mar.nls b/dlls/kernel32/nls/mar.nls index 95b209150a1..8d2b151c958 100644 --- a/dlls/kernel32/nls/mar.nls +++ b/dlls/kernel32/nls/mar.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_MARATHI, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x092e\x0930\x093e\x0920\x0940" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Mlym;" LOCALE_SSHORTDATE L"dd-MM-yyyy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/mki.nls b/dlls/kernel32/nls/mki.nls index f797d60b505..760967dcab1 100644 --- a/dlls/kernel32/nls/mki.nls +++ b/dlls/kernel32/nls/mki.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_MACEDONIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "ìàêåäîíñêè ¼àçèê" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Cyrl;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/mon.nls b/dlls/kernel32/nls/mon.nls index dee1dbb5a1f..72d7e3f1ef7 100644 --- a/dlls/kernel32/nls/mon.nls +++ b/dlls/kernel32/nls/mon.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_MONGOLIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Ìîíãîë õýë" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Cyrl;" LOCALE_SSHORTDATE "yy.MM.dd" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/msb.nls b/dlls/kernel32/nls/msb.nls index 349e567f97a..8e3a8cbabcf 100644 --- a/dlls/kernel32/nls/msb.nls +++ b/dlls/kernel32/nls/msb.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_MALAY, SUBLANG_MALAY_BRUNEI_DARUSSALAM LOCALE_SNATIVELANGNAME "Bahasa Malaysia" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/msl.nls b/dlls/kernel32/nls/msl.nls index b980e306a14..4f9bacb7717 100644 --- a/dlls/kernel32/nls/msl.nls +++ b/dlls/kernel32/nls/msl.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_MALAY, SUBLANG_MALAY_MALAYSIA LOCALE_SNATIVELANGNAME "Bahasa Malaysia" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/nlb.nls b/dlls/kernel32/nls/nlb.nls index 12eec8237d8..e2c9ed11ab5 100644 --- a/dlls/kernel32/nls/nlb.nls +++ b/dlls/kernel32/nls/nlb.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_DUTCH, SUBLANG_DUTCH_BELGIAN LOCALE_SNATIVELANGNAME "Nederlands" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/nld.nls b/dlls/kernel32/nls/nld.nls index 872cf927a95..e5be60f0459 100644 --- a/dlls/kernel32/nls/nld.nls +++ b/dlls/kernel32/nls/nld.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_DUTCH, SUBLANG_DUTCH LOCALE_SNATIVELANGNAME "Nederlands" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d-M-yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/nls.nls b/dlls/kernel32/nls/nls.nls index bac2404987f..f4aa8533c0c 100644 --- a/dlls/kernel32/nls/nls.nls +++ b/dlls/kernel32/nls/nls.nls @@ -134,6 +134,7 @@ STRINGTABLE LANGUAGE LANG_DUTCH, SUBLANG_DUTCH_SURINAM LOCALE_SNATIVELANGNAME "" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d-M-yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/non.nls b/dlls/kernel32/nls/non.nls index 815323e4745..e33611b231a 100644 --- a/dlls/kernel32/nls/non.nls +++ b/dlls/kernel32/nls/non.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK LOCALE_SNATIVELANGNAME "norsk (nynorsk)" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/nor.nls b/dlls/kernel32/nls/nor.nls index f8f52b0ef6c..f7340f34744 100644 --- a/dlls/kernel32/nls/nor.nls +++ b/dlls/kernel32/nls/nor.nls @@ -129,6 +129,7 @@ STRINGTABLE LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL LOCALE_SNATIVELANGNAME "norsk (bokmål)" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/pan.nls b/dlls/kernel32/nls/pan.nls index 7ce38471015..2c237e08693 100644 --- a/dlls/kernel32/nls/pan.nls +++ b/dlls/kernel32/nls/pan.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_PUNJABI, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x0a2a\x0a70\x0a1c\x0a3e\x0a2c\x0a40" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Guru;" LOCALE_SSHORTDATE L"dd-MM-yy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/plk.nls b/dlls/kernel32/nls/plk.nls index 6fd993288c7..05da282a04a 100644 --- a/dlls/kernel32/nls/plk.nls +++ b/dlls/kernel32/nls/plk.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_POLISH, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "polski" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "yyyy-MM-dd" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/ptb.nls b/dlls/kernel32/nls/ptb.nls index 156ad015226..6ca15204d3d 100644 --- a/dlls/kernel32/nls/ptb.nls +++ b/dlls/kernel32/nls/ptb.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN LOCALE_SNATIVELANGNAME "Português" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d/M/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/ptg.nls b/dlls/kernel32/nls/ptg.nls index 80e964c6b7c..38a3e546c12 100644 --- a/dlls/kernel32/nls/ptg.nls +++ b/dlls/kernel32/nls/ptg.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE LOCALE_SNATIVELANGNAME "português" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd-MM-yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/rmc.nls b/dlls/kernel32/nls/rmc.nls index b7452ec1d4e..aff624e2062 100644 --- a/dlls/kernel32/nls/rmc.nls +++ b/dlls/kernel32/nls/rmc.nls @@ -139,6 +139,7 @@ STRINGTABLE LANGUAGE LANG_ROMANSH, SUBLANG_ROMANSH_SWITZERLAND LOCALE_SNATIVELANGNAME "Rumantsch (Svizra)" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd-MM-yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "'" diff --git a/dlls/kernel32/nls/rom.nls b/dlls/kernel32/nls/rom.nls index bc6898483b4..045f9305b8e 100644 --- a/dlls/kernel32/nls/rom.nls +++ b/dlls/kernel32/nls/rom.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ROMANIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "românã" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/rus.nls b/dlls/kernel32/nls/rus.nls index f4fd12f8038..ced98f2bd41 100644 --- a/dlls/kernel32/nls/rus.nls +++ b/dlls/kernel32/nls/rus.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "ðóññêèé" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Cyrl;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/san.nls b/dlls/kernel32/nls/san.nls index 62ef0e24897..ce236d7ce04 100644 --- a/dlls/kernel32/nls/san.nls +++ b/dlls/kernel32/nls/san.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SANSKRIT, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x0938\x0902\x0938\x094d\x0915\x0943\x0924" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Deva;" LOCALE_SSHORTDATE L"dd-MM-yyyy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/sky.nls b/dlls/kernel32/nls/sky.nls index fd6e40d92fe..7fe7ffa4c66 100644 --- a/dlls/kernel32/nls/sky.nls +++ b/dlls/kernel32/nls/sky.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "slovenèina" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d. M. yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/slv.nls b/dlls/kernel32/nls/slv.nls index 2c7b29bf1c1..58cfce93605 100644 --- a/dlls/kernel32/nls/slv.nls +++ b/dlls/kernel32/nls/slv.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "slovenski" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d.M.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/sqi.nls b/dlls/kernel32/nls/sqi.nls index 239bcc37a7a..3a772071286 100644 --- a/dlls/kernel32/nls/sqi.nls +++ b/dlls/kernel32/nls/sqi.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_ALBANIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "shqipe" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "yyyy-MM-dd" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/srb.nls b/dlls/kernel32/nls/srb.nls index 06aa4f1bace..2f0423214e4 100644 --- a/dlls/kernel32/nls/srb.nls +++ b/dlls/kernel32/nls/srb.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC LOCALE_SNATIVELANGNAME "ñðïñêè" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Cyrl;" LOCALE_SSHORTDATE "d.M.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/srl.nls b/dlls/kernel32/nls/srl.nls index cab1113e12b..d334f702541 100644 --- a/dlls/kernel32/nls/srl.nls +++ b/dlls/kernel32/nls/srl.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SERBIAN, SUBLANG_SERBIAN_LATIN LOCALE_SNATIVELANGNAME "srpski" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d.M.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/sve.nls b/dlls/kernel32/nls/sve.nls index 6808138a4d2..14d8c058dbf 100644 --- a/dlls/kernel32/nls/sve.nls +++ b/dlls/kernel32/nls/sve.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SWEDISH, SUBLANG_SWEDISH LOCALE_SNATIVELANGNAME "svenska" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "yyyy-MM-dd" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/svf.nls b/dlls/kernel32/nls/svf.nls index 2e580989bc9..4e217ab54c9 100644 --- a/dlls/kernel32/nls/svf.nls +++ b/dlls/kernel32/nls/svf.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SWEDISH, SUBLANG_SWEDISH_FINLAND LOCALE_SNATIVELANGNAME "svenska" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "d.M.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/swk.nls b/dlls/kernel32/nls/swk.nls index 93e8c9a7c11..79d62c3186c 100644 --- a/dlls/kernel32/nls/swk.nls +++ b/dlls/kernel32/nls/swk.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SWAHILI, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Kiswahili" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "M/d/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/syr.nls b/dlls/kernel32/nls/syr.nls index d1875baf390..8cead3b864b 100644 --- a/dlls/kernel32/nls/syr.nls +++ b/dlls/kernel32/nls/syr.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_SYRIAC, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x0723\x0718\x072a\x071d\x071d\x0710" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"+" + LOCALE_SSCRIPTS L"Syrc;" LOCALE_SSHORTDATE L"dd/MM/yyyy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/tam.nls b/dlls/kernel32/nls/tam.nls index 9eab2fb8bab..00e112bf63d 100644 --- a/dlls/kernel32/nls/tam.nls +++ b/dlls/kernel32/nls/tam.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_TAMIL, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x0ba4\x0bae\x0bbf\x0bb4\x0bcd" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Taml;" LOCALE_SSHORTDATE L"dd-MM-yyyy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/tel.nls b/dlls/kernel32/nls/tel.nls index f9084935f4e..72a4991ecf2 100644 --- a/dlls/kernel32/nls/tel.nls +++ b/dlls/kernel32/nls/tel.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_TELUGU, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME L"\x0c24\x0c46\x0c32\x0c41\x0c17\x0c41" LOCALE_SNEGATIVESIGN L"-" LOCALE_SPOSITIVESIGN L"" + LOCALE_SSCRIPTS L"Telu;" LOCALE_SSHORTDATE L"dd-MM-yy" LOCALE_SSORTNAME L"Default" LOCALE_STHOUSAND L"," diff --git a/dlls/kernel32/nls/tha.nls b/dlls/kernel32/nls/tha.nls index 7adf818a593..42f0a806ad3 100644 --- a/dlls/kernel32/nls/tha.nls +++ b/dlls/kernel32/nls/tha.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_THAI, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "ä·Â" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Thai;" LOCALE_SSHORTDATE "d/M/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/trk.nls b/dlls/kernel32/nls/trk.nls index 64a172e5fd9..7933d4f37b2 100644 --- a/dlls/kernel32/nls/trk.nls +++ b/dlls/kernel32/nls/trk.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Türkçe" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/ttt.nls b/dlls/kernel32/nls/ttt.nls index 1bb177a7abb..9a21d710435 100644 --- a/dlls/kernel32/nls/ttt.nls +++ b/dlls/kernel32/nls/ttt.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_TATAR, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Òàòàð" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" /* FIXME? */ LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/ukr.nls b/dlls/kernel32/nls/ukr.nls index 904bdc5a691..865fd2dbcd6 100644 --- a/dlls/kernel32/nls/ukr.nls +++ b/dlls/kernel32/nls/ukr.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "óêðà¿íüñêà" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Cyrl;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/urd.nls b/dlls/kernel32/nls/urd.nls index 5fdfb9a1356..26ea2edd466 100644 --- a/dlls/kernel32/nls/urd.nls +++ b/dlls/kernel32/nls/urd.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_URDU, SUBLANG_URDU_PAKISTAN LOCALE_SNATIVELANGNAME "ÇõÑÏæ" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Arab;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/uzb.nls b/dlls/kernel32/nls/uzb.nls index b69bc9e665e..b6b0c7b4c86 100644 --- a/dlls/kernel32/nls/uzb.nls +++ b/dlls/kernel32/nls/uzb.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC LOCALE_SNATIVELANGNAME "¡çáåê" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Cyrl;" LOCALE_SSHORTDATE "dd.MM.yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/uzl.nls b/dlls/kernel32/nls/uzl.nls index ba7343f0ee5..c0778d44dd7 100644 --- a/dlls/kernel32/nls/uzl.nls +++ b/dlls/kernel32/nls/uzl.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_UZBEK, SUBLANG_UZBEK_LATIN LOCALE_SNATIVELANGNAME "U'zbek" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/vit.nls b/dlls/kernel32/nls/vit.nls index e3ebe571704..e7236b54439 100644 --- a/dlls/kernel32/nls/vit.nls +++ b/dlls/kernel32/nls/vit.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_VIETNAMESE, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Tiêìng Viêòt Nam" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND "." diff --git a/dlls/kernel32/nls/wal.nls b/dlls/kernel32/nls/wal.nls index 61d4488edad..339307197e9 100644 --- a/dlls/kernel32/nls/wal.nls +++ b/dlls/kernel32/nls/wal.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_WALON, SUBLANG_DEFAULT LOCALE_SNATIVELANGNAME "Walon" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Latn;" LOCALE_SSHORTDATE "dd/MM/yyyy" LOCALE_SSORTNAME "Default" LOCALE_STHOUSAND " " diff --git a/dlls/kernel32/nls/zhh.nls b/dlls/kernel32/nls/zhh.nls index 386e2106b17..d36ee68a097 100644 --- a/dlls/kernel32/nls/zhh.nls +++ b/dlls/kernel32/nls/zhh.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_HONGKONG LOCALE_SNATIVELANGNAME "¤¤¤å(ÁcÅé)" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Hant;" LOCALE_SSHORTDATE "d/M/yyyy" LOCALE_SSORTNAME "Stroke Count" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/zhi.nls b/dlls/kernel32/nls/zhi.nls index b4b29631245..25ba406410f 100644 --- a/dlls/kernel32/nls/zhi.nls +++ b/dlls/kernel32/nls/zhi.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE LOCALE_SNATIVELANGNAME "ÖÐÎÄ(¼òÌå)" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Hans;" LOCALE_SSHORTDATE "d/M/yyyy" LOCALE_SSORTNAME "Pronunciation" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/nls/zhm.nls b/dlls/kernel32/nls/zhm.nls index ae87822eea6..a9a226a197c 100644 --- a/dlls/kernel32/nls/zhm.nls +++ b/dlls/kernel32/nls/zhm.nls @@ -128,6 +128,7 @@ STRINGTABLE LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_MACAU LOCALE_SNATIVELANGNAME L"\x4e2d\x6587(\x7b80\x4f53)" LOCALE_SNEGATIVESIGN "-" LOCALE_SPOSITIVESIGN "" + LOCALE_SSCRIPTS "Hant;" LOCALE_SSHORTDATE "d/M/yyyy" LOCALE_SSORTNAME "Pronunciation" LOCALE_STHOUSAND "," diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c index 0032d17ef92..da558fd63d3 100644 --- a/dlls/kernel32/sync.c +++ b/dlls/kernel32/sync.c @@ -350,8 +350,7 @@ DWORD WINAPI SignalObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn */ void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit ) { - NTSTATUS ret = RtlInitializeCriticalSection( crit ); - if (ret) RtlRaiseStatus( ret ); + InitializeCriticalSectionEx( crit, 0, 0 ); } /*********************************************************************** @@ -372,7 +371,29 @@ void WINAPI InitializeCriticalSection( CRITICAL_SECTION *crit ) */ BOOL WINAPI InitializeCriticalSectionAndSpinCount( CRITICAL_SECTION *crit, DWORD spincount ) { - NTSTATUS ret = RtlInitializeCriticalSectionAndSpinCount( crit, spincount ); + return InitializeCriticalSectionEx( crit, spincount, 0 ); +} + +/*********************************************************************** + * InitializeCriticalSectionEx (KERNEL32.@) + * + * Initialise a critical section with a spin count and flags. + * + * PARAMS + * crit [O] Critical section to initialise. + * spincount [I] Number of times to spin upon contention. + * flags [I] CRITICAL_SECTION_ flags from winbase.h. + * + * RETURNS + * Success: TRUE. + * Failure: Nothing. If the function fails an exception is raised. + * + * NOTES + * spincount is ignored on uni-processor systems. + */ +BOOL WINAPI InitializeCriticalSectionEx( CRITICAL_SECTION *crit, DWORD spincount, DWORD flags ) +{ + NTSTATUS ret = RtlInitializeCriticalSectionEx( crit, spincount, flags ); if (ret) RtlRaiseStatus( ret ); return !ret; } diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index aacae9cb23c..6eed56bd07f 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -130,6 +130,49 @@ static void testCursor(HANDLE hCon, COORD sbSize) ERROR_INVALID_PARAMETER, GetLastError()); } +static void testCursorInfo(HANDLE hCon) +{ + BOOL ret; + CONSOLE_CURSOR_INFO info; + + SetLastError(0xdeadbeef); + ret = GetConsoleCursorInfo(NULL, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n", + ERROR_INVALID_HANDLE, GetLastError()); + + SetLastError(0xdeadbeef); + info.dwSize = -1; + ret = GetConsoleCursorInfo(NULL, &info); + ok(!ret, "Expected failure\n"); + ok(info.dwSize == -1, "Expected no change for dwSize\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError: expecting %u got %u\n", + ERROR_INVALID_HANDLE, GetLastError()); + + /* Test the correct call first to distinguish between win9x and the rest */ + SetLastError(0xdeadbeef); + ret = GetConsoleCursorInfo(hCon, &info); + ok(ret, "Expected success\n"); + ok(info.dwSize == 25 || + info.dwSize == 12 /* win9x */, + "Expected 12 or 25, got %d\n", info.dwSize); + ok(info.bVisible, "Expected the cursor to be visible\n"); + ok(GetLastError() == 0xdeadbeef, "GetLastError: expecting %u got %u\n", + 0xdeadbeef, GetLastError()); + + if (info.dwSize == 12) + { + skip("NULL CONSOLE_CURSOR_INFO will crash on win9x\n"); + return; + } + + SetLastError(0xdeadbeef); + ret = GetConsoleCursorInfo(hCon, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_ACCESS, "GetLastError: expecting %u got %u\n", + ERROR_INVALID_ACCESS, GetLastError()); +} + static void testWriteSimple(HANDLE hCon, COORD sbSize) { COORD c; @@ -863,6 +906,8 @@ START_TEST(console) /* Non interactive tests */ testCursor(hConOut, sbi.dwSize); + /* test parameters (FIXME: test functionality) */ + testCursorInfo(hConOut); /* will test wrapped (on/off) & processed (on/off) strings output */ testWrite(hConOut, sbi.dwSize); /* will test line scrolling at the bottom of the screen */ diff --git a/dlls/kernel32/tests/debugger.c b/dlls/kernel32/tests/debugger.c index 3d8d7f5547b..003403fdc60 100644 --- a/dlls/kernel32/tests/debugger.c +++ b/dlls/kernel32/tests/debugger.c @@ -137,6 +137,7 @@ static void doDebugger(int argc, char** argv) logfile=(argc >= 4 ? argv[3] : NULL); blackbox.pid=(argc >= 5 ? atol(argv[4]) : 0); + blackbox.attach_err=0; if (strstr(myARGV[2], "attach")) { blackbox.attach_rc=DebugActiveProcess(blackbox.pid); @@ -147,6 +148,7 @@ static void doDebugger(int argc, char** argv) blackbox.attach_rc=TRUE; debug_event=(argc >= 6 ? (HANDLE)atol(argv[5]) : NULL); + blackbox.debug_err=0; if (debug_event && strstr(myARGV[2], "event")) { blackbox.debug_rc=SetEvent(debug_event); @@ -163,6 +165,7 @@ static void doDebugger(int argc, char** argv) WaitForSingleObject(start_event, INFINITE); } + blackbox.nokill_err=0; if (strstr(myARGV[2], "nokill")) { blackbox.nokill_rc=pDebugSetProcessKillOnExit(FALSE); @@ -172,6 +175,7 @@ static void doDebugger(int argc, char** argv) else blackbox.nokill_rc=TRUE; + blackbox.detach_err=0; if (strstr(myARGV[2], "detach")) { blackbox.detach_rc=pDebugActiveProcessStop(blackbox.pid); diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c index 7d83b255a4d..d1ac61795e1 100644 --- a/dlls/kernel32/tests/thread.c +++ b/dlls/kernel32/tests/thread.c @@ -21,6 +21,7 @@ /* Define _WIN32_WINNT to get SetThreadIdealProcessor on Windows */ #define _WIN32_WINNT 0x0500 +#include #include #include @@ -99,6 +100,57 @@ In addition there are no checks that the inheritance works properly in CreateThread */ +/* Functions to ensure that from a group of threads, only one executes + certain chunks of code at a time, and we know which one is executing + it. It basically makes multithreaded execution linear, which defeats + the purpose of multiple threads, but makes testing easy. */ +static HANDLE all_synced; +static LONG num_syncing_threads, num_synced; + +static void init_thread_sync_helpers(LONG num_threads) +{ + all_synced = CreateEvent(NULL, FALSE, FALSE, NULL); + ok(all_synced != NULL, "CreateEvent failed\n"); + num_syncing_threads = num_threads; + num_synced = 0; +} + +static BOOL sync_threads_and_run_one(DWORD sync_id, DWORD my_id) +{ + LONG num = InterlockedIncrement(&num_synced); + assert(0 < num && num <= num_syncing_threads); + if (num == num_syncing_threads) + /* FIXME: MSDN claims PulseEvent is unreliable. For a test this isn't + so important, but we could use condition variables with more effort. + The given approach is clearer, though. */ + PulseEvent(all_synced); + else + { + DWORD ret = WaitForSingleObject(all_synced, 60000); + ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); + } + return sync_id == my_id; +} + +static void resync_after_run(void) +{ + LONG num = InterlockedDecrement(&num_synced); + assert(0 <= num && num < num_syncing_threads); + if (num == 0) + PulseEvent(all_synced); + else + { + DWORD ret = WaitForSingleObject(all_synced, 60000); + ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); + } +} + +static void cleanup_thread_sync_helpers(void) +{ + CloseHandle(all_synced); + all_synced = NULL; +} + DWORD tlsIndex; typedef struct { @@ -953,6 +1005,181 @@ static void test_RegisterWaitForSingleObject(void) ok(ret, "UnregisterWait failed with error %d\n", GetLastError()); } +static DWORD TLS_main; +static DWORD TLS_index0, TLS_index1; + +static DWORD WINAPI TLS_InheritanceProc(LPVOID p) +{ + /* We should NOT inherit the TLS values from our parent or from the + main thread. */ + LPVOID val; + + val = TlsGetValue(TLS_main); + ok(val == NULL, "TLS inheritance failed\n"); + + val = TlsGetValue(TLS_index0); + ok(val == NULL, "TLS inheritance failed\n"); + + val = TlsGetValue(TLS_index1); + ok(val == NULL, "TLS inheritance failed\n"); + + return 0; +} + +/* Basic TLS usage test. Make sure we can create slots and the values we + store in them are separate among threads. Also test TLS value + inheritance with TLS_InheritanceProc. */ +static DWORD WINAPI TLS_ThreadProc(LPVOID p) +{ + LONG id = (LONG) p; + LPVOID val; + BOOL ret; + + if (sync_threads_and_run_one(0, id)) + { + TLS_index0 = TlsAlloc(); + ok(TLS_index0 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n"); + } + resync_after_run(); + + if (sync_threads_and_run_one(1, id)) + { + TLS_index1 = TlsAlloc(); + ok(TLS_index1 != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n"); + + /* Slot indices should be different even if created in different + threads. */ + ok(TLS_index0 != TLS_index1, "TlsAlloc failed\n"); + + /* Both slots should be initialized to NULL */ + val = TlsGetValue(TLS_index0); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == NULL, "TLS slot not initialized correctly\n"); + + val = TlsGetValue(TLS_index1); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == NULL, "TLS slot not initialized correctly\n"); + } + resync_after_run(); + + if (sync_threads_and_run_one(0, id)) + { + val = TlsGetValue(TLS_index0); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == NULL, "TLS slot not initialized correctly\n"); + + val = TlsGetValue(TLS_index1); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == NULL, "TLS slot not initialized correctly\n"); + + ret = TlsSetValue(TLS_index0, (LPVOID) 1); + ok(ret, "TlsSetValue failed\n"); + + ret = TlsSetValue(TLS_index1, (LPVOID) 2); + ok(ret, "TlsSetValue failed\n"); + + val = TlsGetValue(TLS_index0); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n"); + + val = TlsGetValue(TLS_index1); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n"); + } + resync_after_run(); + + if (sync_threads_and_run_one(1, id)) + { + val = TlsGetValue(TLS_index0); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == NULL, "TLS slot not initialized correctly\n"); + + val = TlsGetValue(TLS_index1); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == NULL, "TLS slot not initialized correctly\n"); + + ret = TlsSetValue(TLS_index0, (LPVOID) 3); + ok(ret, "TlsSetValue failed\n"); + + ret = TlsSetValue(TLS_index1, (LPVOID) 4); + ok(ret, "TlsSetValue failed\n"); + + val = TlsGetValue(TLS_index0); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == (LPVOID) 3, "TLS slot not initialized correctly\n"); + + val = TlsGetValue(TLS_index1); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == (LPVOID) 4, "TLS slot not initialized correctly\n"); + } + resync_after_run(); + + if (sync_threads_and_run_one(0, id)) + { + HANDLE thread; + DWORD waitret; + + val = TlsGetValue(TLS_index0); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == (LPVOID) 1, "TLS slot not initialized correctly\n"); + + val = TlsGetValue(TLS_index1); + ok(GetLastError() == ERROR_SUCCESS, "TlsGetValue failed\n"); + ok(val == (LPVOID) 2, "TLS slot not initialized correctly\n"); + + thread = CreateThread(NULL, 0, TLS_InheritanceProc, 0, 0, NULL); + ok(thread != NULL, "CreateThread failed\n"); + waitret = WaitForSingleObject(thread, 60000); + ok(waitret == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); + CloseHandle(thread); + + ret = TlsFree(TLS_index0); + ok(ret, "TlsFree failed\n"); + } + resync_after_run(); + + if (sync_threads_and_run_one(1, id)) + { + ret = TlsFree(TLS_index1); + ok(ret, "TlsFree failed\n"); + } + resync_after_run(); + + return 0; +} + +static void test_TLS(void) +{ + HANDLE threads[2]; + LONG i; + DWORD ret; + BOOL suc; + + init_thread_sync_helpers(2); + + /* Allocate a TLS slot in the main thread to test for inheritance. */ + TLS_main = TlsAlloc(); + ok(TLS_main != TLS_OUT_OF_INDEXES, "TlsAlloc failed\n"); + suc = TlsSetValue(TLS_main, (LPVOID) 4114); + ok(suc, "TlsSetValue failed\n"); + + for (i = 0; i < 2; ++i) + { + threads[i] = CreateThread(NULL, 0, TLS_ThreadProc, (LPVOID) i, 0, NULL); + ok(threads[i] != NULL, "CreateThread failed\n"); + } + + ret = WaitForMultipleObjects(2, threads, TRUE, 60000); + ok(ret == WAIT_OBJECT_0, "WaitForMultipleObjects failed\n"); + + for (i = 0; i < 2; ++i) + CloseHandle(threads[i]); + + suc = TlsFree(TLS_main); + ok(suc, "TlsFree failed\n"); + cleanup_thread_sync_helpers(); +} + START_TEST(thread) { HINSTANCE lib; @@ -1012,4 +1239,5 @@ START_TEST(thread) #endif test_QueueUserWorkItem(); test_RegisterWaitForSingleObject(); + test_TLS(); } diff --git a/dlls/localspl/tests/localmon.c b/dlls/localspl/tests/localmon.c index 4d75a4cff2b..26eea89b383 100644 --- a/dlls/localspl/tests/localmon.c +++ b/dlls/localspl/tests/localmon.c @@ -1356,6 +1356,7 @@ START_TEST(localmon) DWORD numentries; DWORD res; + LoadLibraryA("winspool.drv"); /* This DLL does not exist on Win9x */ hdll = LoadLibraryA("localspl.dll"); if (!hdll) { diff --git a/dlls/mapi32/tests/prop.c b/dlls/mapi32/tests/prop.c index adc1d85b91a..a2b92891934 100644 --- a/dlls/mapi32/tests/prop.c +++ b/dlls/mapi32/tests/prop.c @@ -824,13 +824,16 @@ static void test_ScCopyRelocProps(void) sc = pScCopyProps(1, &pvProp, buffer, &ulCount); ok(sc == S_OK, "wrong ret %d\n", sc); - ok(lpResProp->ulPropTag == pvProp.ulPropTag, "wrong tag %x\n",lpResProp->ulPropTag); - ok(lpResProp->Value.MVszA.cValues == 1, "wrong cValues %d\n", lpResProp->Value.MVszA.cValues); - ok(lpResProp->Value.MVszA.lppszA[0] == buffer + sizeof(SPropValue) + sizeof(char*), - "wrong lppszA[0] %p\n",lpResProp->Value.MVszA.lppszA[0]); - ok(ulCount == sizeof(SPropValue) + sizeof(char*) + 5, "wrong count %d\n", ulCount); - ok(!strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA), - "wrong string '%s'\n", lpResProp->Value.MVszA.lppszA[0]); + if(sc == S_OK) + { + ok(lpResProp->ulPropTag == pvProp.ulPropTag, "wrong tag %x\n",lpResProp->ulPropTag); + ok(lpResProp->Value.MVszA.cValues == 1, "wrong cValues %d\n", lpResProp->Value.MVszA.cValues); + ok(lpResProp->Value.MVszA.lppszA[0] == buffer + sizeof(SPropValue) + sizeof(char*), + "wrong lppszA[0] %p\n",lpResProp->Value.MVszA.lppszA[0]); + ok(ulCount == sizeof(SPropValue) + sizeof(char*) + 5, "wrong count %d\n", ulCount); + ok(!strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA), + "wrong string '%s'\n", lpResProp->Value.MVszA.lppszA[0]); + } memcpy(buffer2, buffer, sizeof(buffer)); @@ -845,18 +848,21 @@ static void test_ScCopyRelocProps(void) lpResProp = (LPSPropValue)buffer2; ok(sc == S_OK, "wrong ret %d\n", sc); - ok(lpResProp->ulPropTag == pvProp.ulPropTag, "wrong tag %x\n",lpResProp->ulPropTag); - ok(lpResProp->Value.MVszA.cValues == 1, "wrong cValues %d\n", lpResProp->Value.MVszA.cValues); - ok(lpResProp->Value.MVszA.lppszA[0] == buffer2 + sizeof(SPropValue) + sizeof(char*), - "wrong lppszA[0] %p\n",lpResProp->Value.MVszA.lppszA[0]); - /* Native has a bug whereby it calculates the size correctly when copying - * but when relocating does not (presumably it uses UlPropSize() which - * ignores multivalue pointers). Wine returns the correct value. - */ - ok(ulCount == sizeof(SPropValue) + sizeof(char*) + 5 || ulCount == sizeof(SPropValue) + 5, - "wrong count %d\n", ulCount); - ok(!strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA), - "wrong string '%s'\n", lpResProp->Value.MVszA.lppszA[0]); + if(sc == S_OK) + { + ok(lpResProp->ulPropTag == pvProp.ulPropTag, "wrong tag %x\n",lpResProp->ulPropTag); + ok(lpResProp->Value.MVszA.cValues == 1, "wrong cValues %d\n", lpResProp->Value.MVszA.cValues); + ok(lpResProp->Value.MVszA.lppszA[0] == buffer2 + sizeof(SPropValue) + sizeof(char*), + "wrong lppszA[0] %p\n",lpResProp->Value.MVszA.lppszA[0]); + /* Native has a bug whereby it calculates the size correctly when copying + * but when relocating does not (presumably it uses UlPropSize() which + * ignores multivalue pointers). Wine returns the correct value. + */ + ok(ulCount == sizeof(SPropValue) + sizeof(char*) + 5 || ulCount == sizeof(SPropValue) + 5, + "wrong count %d\n", ulCount); + ok(!strcmp(lpResProp->Value.MVszA.lppszA[0], szTestA), + "wrong string '%s'\n", lpResProp->Value.MVszA.lppszA[0]); + } /* Native crashes with lpNew or lpOld set to NULL so skip testing this */ } diff --git a/dlls/mciavi32/mmoutput.c b/dlls/mciavi32/mmoutput.c index 8c8bdc22f4c..f7118ff6ca3 100644 --- a/dlls/mciavi32/mmoutput.c +++ b/dlls/mciavi32/mmoutput.c @@ -28,8 +28,6 @@ static BOOL MCIAVI_GetInfoAudio(WINE_MCIAVI* wma, const MMCKINFO* mmckList, MMCK { MMCKINFO mmckInfo; - mmioRead(wma->hFile, (LPSTR)&wma->ash_audio, sizeof(wma->ash_audio)); - TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_audio.fccType)), HIBYTE(LOWORD(wma->ash_audio.fccType)), LOBYTE(HIWORD(wma->ash_audio.fccType)), @@ -91,8 +89,6 @@ static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI* wma, const MMCKINFO* mmckList, MMCK { MMCKINFO mmckInfo; - mmioRead(wma->hFile, (LPSTR)&wma->ash_video, sizeof(wma->ash_video)); - TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_video.fccType)), HIBYTE(LOWORD(wma->ash_video.fccType)), LOBYTE(HIWORD(wma->ash_video.fccType)), @@ -261,6 +257,7 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma) MMCKINFO mmckHead; MMCKINFO mmckList; MMCKINFO mmckInfo; + AVIStreamHeader strh; struct AviListBuild alb; DWORD stream_n; @@ -320,34 +317,40 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma) continue; } - TRACE("Stream #%d fccType %4.4s\n", stream_n, (LPSTR)&mmckStream.fccType); + mmioRead(wma->hFile, (LPSTR)&strh, sizeof(strh)); + + TRACE("Stream #%d fccType %4.4s\n", stream_n, (LPSTR)&strh.fccType); - if (mmckStream.fccType == streamtypeVIDEO) + if (strh.fccType == streamtypeVIDEO) { TRACE("found video stream\n"); if (wma->inbih) WARN("ignoring another video stream\n"); else { + wma->ash_audio = strh; + if (!MCIAVI_GetInfoVideo(wma, &mmckList, &mmckStream)) return FALSE; wma->video_stream_n = stream_n; } } - else if (mmckStream.fccType == streamtypeAUDIO) + else if (strh.fccType == streamtypeAUDIO) { TRACE("found audio stream\n"); if (wma->lpWaveFormat) WARN("ignoring another audio stream\n"); else { + wma->ash_video = strh; + if (!MCIAVI_GetInfoAudio(wma, &mmckList, &mmckStream)) return FALSE; wma->audio_stream_n = stream_n; } } else - TRACE("Unsupported stream type %4.4s\n", (LPSTR)&mmckStream.fccType); + TRACE("Unsupported stream type %4.4s\n", (LPSTR)&strh.fccType); mmioAscend(wma->hFile, &mmckList, 0); } diff --git a/dlls/mpr/wnet.c b/dlls/mpr/wnet.c index 32bc255820c..bf4ddb85807 100644 --- a/dlls/mpr/wnet.c +++ b/dlls/mpr/wnet.c @@ -1312,6 +1312,7 @@ DWORD WINAPI WNetGetResourceInformationA( LPNETRESOURCEA lpNetResource, ret = _thunkNetResourceArrayAToW(lpNetResource, &count, lpNetResourceW, &size); if (ret == WN_MORE_DATA) { + HeapFree(GetProcessHeap(), 0, lpNetResourceW); lpNetResourceW = HeapAlloc(GetProcessHeap(), 0, size); if (lpNetResourceW) ret = _thunkNetResourceArrayAToW(lpNetResource, @@ -1343,6 +1344,7 @@ DWORD WINAPI WNetGetResourceInformationA( LPNETRESOURCEA lpNetResource, { ret = _thunkNetResourceArrayWToA(lpBufferW, &count, lpBuffer, cbBuffer); + HeapFree(GetProcessHeap(), 0, lpNetResourceW); lpNetResourceW = lpBufferW; size = sizeof(NETRESOURCEA); size += WideCharToMultiByte(CP_ACP, 0, lpNetResourceW->lpRemoteName, diff --git a/dlls/mscms/tests/profile.c b/dlls/mscms/tests/profile.c index efcd3b5edc2..7d77baaa5c6 100644 --- a/dlls/mscms/tests/profile.c +++ b/dlls/mscms/tests/profile.c @@ -569,7 +569,7 @@ static void check_registry(BOOL *has_space_rgb) dwNameLen = sizeof(szName); dwDataLen = sizeof(szData); res = RegEnumValueA( hkIcmKey, i, szName, &dwNameLen, NULL, &dwType, (LPBYTE)szData, &dwDataLen ); - if (strcmp(szName, "RGB") == 0) + if (!strncmp(szName, "RGB", 3)) *has_space_rgb = TRUE; if (res != ERROR_SUCCESS) { diff --git a/dlls/mshtml/htmldoc3.c b/dlls/mshtml/htmldoc3.c index 4fbd131c38b..92ed1cc3247 100644 --- a/dlls/mshtml/htmldoc3.c +++ b/dlls/mshtml/htmldoc3.c @@ -108,8 +108,31 @@ static HRESULT WINAPI HTMLDocument3_createTextNode(IHTMLDocument3 *iface, BSTR t IHTMLDOMNode **newTextNode) { HTMLDocument *This = HTMLDOC3_THIS(iface); - FIXME("(%p)->(%s %p)\n", This, debugstr_w(text), newTextNode); - return E_NOTIMPL; + nsIDOMDocument *nsdoc; + nsIDOMText *nstext; + HTMLDOMNode *node; + nsAString text_str; + nsresult nsres; + + TRACE("(%p)->(%s %p)\n", This, debugstr_w(text), newTextNode); + + nsIWebNavigation_GetDocument(This->nscontainer->navigation, &nsdoc); + + nsAString_Init(&text_str, text); + nsres = nsIDOMDocument_CreateTextNode(nsdoc, &text_str, &nstext); + nsAString_Finish(&text_str); + nsIDOMDocument_Release(nsdoc); + if(NS_FAILED(nsres)) { + ERR("CreateTextNode failed: %08x\n", nsres); + return E_FAIL; + } + + node = HTMLDOMTextNode_Create(This, (nsIDOMNode*)nstext); + nsIDOMElement_Release(nstext); + + *newTextNode = HTMLDOMNODE(node); + IHTMLDOMNode_AddRef(HTMLDOMNODE(node)); + return S_OK; } static HRESULT WINAPI HTMLDocument3_get_documentElement(IHTMLDocument3 *iface, IHTMLElement **p) diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index d4e1d4d129b..7c20c2caaf5 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -252,8 +252,23 @@ static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strA static HRESULT WINAPI HTMLElement_put_className(IHTMLElement *iface, BSTR v) { HTMLElement *This = HTMLELEM_THIS(iface); - FIXME("(%p)->(%s)\n", This, debugstr_w(v)); - return E_NOTIMPL; + nsAString classname_str; + nsresult nsres; + + TRACE("(%p)->(%s)\n", This, debugstr_w(v)); + + if(!This->nselem) { + FIXME("NULL nselem\n"); + return E_NOTIMPL; + } + + nsAString_Init(&classname_str, v); + nsres = nsIDOMHTMLElement_SetClassName(This->nselem, &classname_str); + nsAString_Finish(&classname_str); + if(NS_FAILED(nsres)) + ERR("SetClassName failed: %08x\n", nsres); + + return S_OK; } static HRESULT WINAPI HTMLElement_get_className(IHTMLElement *iface, BSTR *p) @@ -276,7 +291,7 @@ static HRESULT WINAPI HTMLElement_get_className(IHTMLElement *iface, BSTR *p) if(NS_SUCCEEDED(nsres)) { const PRUnichar *class; nsAString_GetData(&class_str, &class); - *p = SysAllocString(class); + *p = *class ? SysAllocString(class) : NULL; }else { ERR("GetClassName failed: %08x\n", nsres); hres = E_FAIL; @@ -428,8 +443,10 @@ static HRESULT WINAPI HTMLElement_get_onhelp(IHTMLElement *iface, VARIANT *p) static HRESULT WINAPI HTMLElement_put_onclick(IHTMLElement *iface, VARIANT v) { HTMLElement *This = HTMLELEM_THIS(iface); - FIXME("(%p)->()\n", This); - return E_NOTIMPL; + + TRACE("(%p)->()\n", This); + + return set_node_event(&This->node, EVENTID_CLICK, &v); } static HRESULT WINAPI HTMLElement_get_onclick(IHTMLElement *iface, VARIANT *p) @@ -470,8 +487,10 @@ static HRESULT WINAPI HTMLElement_get_onkeydown(IHTMLElement *iface, VARIANT *p) static HRESULT WINAPI HTMLElement_put_onkeyup(IHTMLElement *iface, VARIANT v) { HTMLElement *This = HTMLELEM_THIS(iface); - FIXME("(%p)->()\n", This); - return E_NOTIMPL; + + TRACE("(%p)->()\n", This); + + return set_node_event(&This->node, EVENTID_KEYUP, &v); } static HRESULT WINAPI HTMLElement_get_onkeyup(IHTMLElement *iface, VARIANT *p) @@ -575,15 +594,41 @@ static HRESULT WINAPI HTMLElement_get_document(IHTMLElement *iface, IDispatch ** static HRESULT WINAPI HTMLElement_put_title(IHTMLElement *iface, BSTR v) { HTMLElement *This = HTMLELEM_THIS(iface); - FIXME("(%p)->(%s)\n", This, debugstr_w(v)); - return E_NOTIMPL; + nsAString title_str; + nsresult nsres; + + TRACE("(%p)->(%s)\n", This, debugstr_w(v)); + + nsAString_Init(&title_str, v); + nsres = nsIDOMHTMLElement_SetTitle(This->nselem, &title_str); + nsAString_Finish(&title_str); + if(NS_FAILED(nsres)) + ERR("SetTitle failed: %08x\n", nsres); + + return S_OK; } static HRESULT WINAPI HTMLElement_get_title(IHTMLElement *iface, BSTR *p) { HTMLElement *This = HTMLELEM_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsAString title_str; + nsresult nsres; + + TRACE("(%p)->(%p)\n", This, p); + + nsAString_Init(&title_str, NULL); + nsres = nsIDOMHTMLElement_GetTitle(This->nselem, &title_str); + if(NS_SUCCEEDED(nsres)) { + const PRUnichar *title; + + nsAString_GetData(&title_str, &title); + *p = *title ? SysAllocString(title) : NULL; + }else { + ERR("GetTitle failed: %08x\n", nsres); + return E_FAIL; + } + + return S_OK; } static HRESULT WINAPI HTMLElement_put_language(IHTMLElement *iface, BSTR v) @@ -667,8 +712,27 @@ static HRESULT WINAPI HTMLElement_get_offsetLeft(IHTMLElement *iface, long *p) static HRESULT WINAPI HTMLElement_get_offsetTop(IHTMLElement *iface, long *p) { HTMLElement *This = HTMLELEM_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsIDOMNSHTMLElement *nselem; + PRInt32 top = 0; + nsresult nsres; + + TRACE("(%p)->(%p)\n", This, p); + + nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem); + if(NS_FAILED(nsres)) { + ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres); + return E_FAIL; + } + + nsres = nsIDOMNSHTMLElement_GetOffsetTop(nselem, &top); + nsIDOMNSHTMLElement_Release(nselem); + if(NS_FAILED(nsres)) { + ERR("GetOffsetTop failed: %08x\n", nsres); + return E_FAIL; + } + + *p = top; + return S_OK; } static HRESULT WINAPI HTMLElement_get_offsetWidth(IHTMLElement *iface, long *p) @@ -1369,6 +1433,7 @@ static const tid_t HTMLElement_iface_tids[] = { IHTMLElement2_tid, 0 }; + static dispex_static_data_t HTMLElement_dispex = { NULL, DispHTMLUnknownElement_tid, diff --git a/dlls/mshtml/htmlelem2.c b/dlls/mshtml/htmlelem2.c index fa4457acd03..d12c60c9b6b 100644 --- a/dlls/mshtml/htmlelem2.c +++ b/dlls/mshtml/htmlelem2.c @@ -383,15 +383,49 @@ static HRESULT WINAPI HTMLElement2_removeExpression(IHTMLElement2 *iface, BSTR p static HRESULT WINAPI HTMLElement2_put_tabIndex(IHTMLElement2 *iface, short v) { HTMLElement *This = HTMLELEM2_THIS(iface); - FIXME("(%p)->(%d)\n", This, v); - return E_NOTIMPL; + nsIDOMNSHTMLElement *nselem; + nsresult nsres; + + TRACE("(%p)->(%d)\n", This, v); + + nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem); + if(NS_FAILED(nsres)) { + ERR("Could not get nsIDOMHTMLNSElement: %08x\n", nsres); + return S_OK; + } + + nsres = nsIDOMNSHTMLElement_SetTabIndex(nselem, v); + nsIDOMNSHTMLElement_Release(nselem); + if(NS_FAILED(nsres)) + ERR("GetTabIndex failed: %08x\n", nsres); + + return S_OK; } static HRESULT WINAPI HTMLElement2_get_tabIndex(IHTMLElement2 *iface, short *p) { HTMLElement *This = HTMLELEM2_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsIDOMNSHTMLElement *nselem; + PRInt32 index = 0; + nsresult nsres; + + TRACE("(%p)->(%p)\n", This, p); + + nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem); + if(NS_FAILED(nsres)) { + ERR("Could not get nsIDOMHTMLNSElement: %08x\n", nsres); + return E_FAIL; + } + + nsres = nsIDOMNSHTMLElement_GetTabIndex(nselem, &index); + nsIDOMNSHTMLElement_Release(nselem); + if(NS_FAILED(nsres)) { + ERR("GetTabIndex failed: %08x\n", nsres); + return E_FAIL; + } + + *p = index; + return S_OK; } static HRESULT WINAPI HTMLElement2_focus(IHTMLElement2 *iface) diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c index 73c0981c2e4..f98e3a15c53 100644 --- a/dlls/mshtml/htmlevent.c +++ b/dlls/mshtml/htmlevent.c @@ -35,18 +35,46 @@ struct event_target_t { IDispatch *event_table[EVENTID_LAST]; }; +static const WCHAR changeW[] = {'c','h','a','n','g','e',0}; +static const WCHAR onchangeW[] = {'o','n','c','h','a','n','g','e',0}; + +static const WCHAR clickW[] = {'c','l','i','c','k',0}; +static const WCHAR onclickW[] = {'o','n','c','l','i','c','k',0}; + +static const WCHAR keyupW[] = {'k','e','y','u','p',0}; +static const WCHAR onkeyupW[] = {'o','n','k','e','y','u','p',0}; + static const WCHAR loadW[] = {'l','o','a','d',0}; static const WCHAR onloadW[] = {'o','n','l','o','a','d',0}; typedef struct { LPCWSTR name; LPCWSTR attr_name; + DWORD flags; } event_info_t; +#define EVENT_DEFAULTLISTENER 0x0001 + static const event_info_t event_info[] = { - {loadW, onloadW} + {changeW, onchangeW, EVENT_DEFAULTLISTENER}, + {clickW, onclickW, EVENT_DEFAULTLISTENER}, + {keyupW, onkeyupW, EVENT_DEFAULTLISTENER}, + {loadW, onloadW, 0} }; +eventid_t str_to_eid(LPCWSTR str) +{ + int i; + + for(i=0; i < sizeof(event_info)/sizeof(event_info[0]); i++) { + if(!strcmpW(event_info[i].name, str)) + return i; + } + + ERR("unknown type %s\n", debugstr_w(str)); + return EVENTID_LAST; +} + typedef struct { const IHTMLEventObjVtbl *lpIHTMLEventObjVtbl; LONG ref; @@ -374,13 +402,46 @@ void fire_event(HTMLDocument *doc, eventid_t eid, nsIDOMNode *target) if(node->event_target && node->event_target->event_table[eid]) { doc->window->event = create_event(); + TRACE("%s >>>\n", debugstr_w(event_info[eid].name)); call_disp_func(doc, node->event_target->event_table[eid]); + TRACE("%s <<<\n", debugstr_w(event_info[eid].name)); IHTMLEventObj_Release(doc->window->event); doc->window->event = NULL; } } +static HRESULT set_node_event_disp(HTMLDOMNode *node, eventid_t eid, IDispatch *disp) +{ + if(!node->event_target) + node->event_target = heap_alloc_zero(sizeof(event_target_t)); + else if(node->event_target->event_table[eid]) + IDispatch_Release(node->event_target->event_table[eid]); + + IDispatch_AddRef(disp); + node->event_target->event_table[eid] = disp; + + if((event_info[eid].flags & EVENT_DEFAULTLISTENER) && !node->doc->nscontainer->event_vector[eid]) { + node->doc->nscontainer->event_vector[eid] = TRUE; + add_nsevent_listener(node->doc->nscontainer, event_info[eid].name); + } + + return S_OK; +} + +HRESULT set_node_event(HTMLDOMNode *node, eventid_t eid, VARIANT *var) +{ + switch(V_VT(var)) { + case VT_DISPATCH: + return set_node_event_disp(node, eid, V_DISPATCH(var)); + + default: + FIXME("not supported vt=%d\n", V_VT(var)); + } + + return E_NOTIMPL; +} + void check_event_attr(HTMLDocument *doc, nsIDOMElement *nselem) { const PRUnichar *attr_value; @@ -406,9 +467,8 @@ void check_event_attr(HTMLDocument *doc, nsIDOMElement *nselem) disp = script_parse_event(doc, attr_value); if(disp) { node = get_node(doc, (nsIDOMNode*)nselem, TRUE); - if(!node->event_target) - node->event_target = heap_alloc_zero(sizeof(event_target_t)); - node->event_target->event_table[i] = disp; + set_node_event_disp(node, i, disp); + IDispatch_Release(disp); } } } diff --git a/dlls/mshtml/htmlimg.c b/dlls/mshtml/htmlimg.c index 92647be9a7b..a2494dfb0fb 100644 --- a/dlls/mshtml/htmlimg.c +++ b/dlls/mshtml/htmlimg.c @@ -35,6 +35,8 @@ typedef struct { HTMLElement element; const IHTMLImgElementVtbl *lpHTMLImgElementVtbl; + + nsIDOMHTMLImageElement *nsimg; } HTMLImgElement; #define HTMLIMG(x) ((IHTMLImgElement*) &(x)->lpHTMLImgElementVtbl) @@ -240,8 +242,18 @@ static HRESULT WINAPI HTMLImgElement_get_alt(IHTMLImgElement *iface, BSTR *p) static HRESULT WINAPI HTMLImgElement_put_src(IHTMLImgElement *iface, BSTR v) { HTMLImgElement *This = HTMLIMG_THIS(iface); - FIXME("(%p)->(%s)\n", This, debugstr_w(v)); - return E_NOTIMPL; + nsAString src_str; + nsresult nsres; + + TRACE("(%p)->(%s)\n", This, debugstr_w(v)); + + nsAString_Init(&src_str, v); + nsres = nsIDOMHTMLImageElement_SetSrc(This->nsimg, &src_str); + nsAString_Finish(&src_str); + if(NS_FAILED(nsres)) + ERR("SetSrc failed: %08x\n", nsres); + + return NS_OK; } static HRESULT WINAPI HTMLImgElement_get_src(IHTMLImgElement *iface, BSTR *p) @@ -516,6 +528,9 @@ static void HTMLImgElement_destructor(HTMLDOMNode *iface) { HTMLImgElement *This = HTMLIMG_NODE_THIS(iface); + if(This->nsimg) + nsIDOMHTMLImageElement_Release(This->nsimg); + HTMLElement_destructor(&This->element.node); } @@ -544,10 +559,15 @@ static dispex_static_data_t HTMLImgElement_dispex = { HTMLElement *HTMLImgElement_Create(nsIDOMHTMLElement *nselem) { HTMLImgElement *ret = heap_alloc_zero(sizeof(HTMLImgElement)); + nsresult nsres; ret->lpHTMLImgElementVtbl = &HTMLImgElementVtbl; ret->element.node.vtbl = &HTMLImgElementImplVtbl; + nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLImageElement, (void**)&ret->nsimg); + if(NS_FAILED(nsres)) + ERR("Could not get nsIDOMHTMLImageElement: %08x\n", nsres); + init_dispex(&ret->element.node.dispex, (IUnknown*)HTMLIMG(ret), &HTMLImgElement_dispex); HTMLElement_Init(&ret->element); diff --git a/dlls/mshtml/htmlinput.c b/dlls/mshtml/htmlinput.c index 92a1f48541a..f8a646650ac 100644 --- a/dlls/mshtml/htmlinput.c +++ b/dlls/mshtml/htmlinput.c @@ -226,8 +226,15 @@ static HRESULT WINAPI HTMLInputElement_get_status(IHTMLInputElement *iface, VARI static HRESULT WINAPI HTMLInputElement_put_disabled(IHTMLInputElement *iface, VARIANT_BOOL v) { HTMLInputElement *This = HTMLINPUT_THIS(iface); - FIXME("(%p)->(%x)\n", This, v); - return E_NOTIMPL; + nsresult nsres; + + TRACE("(%p)->(%x)\n", This, v); + + nsres = nsIDOMHTMLInputElement_SetDisabled(This->nsinput, v != VARIANT_FALSE); + if(NS_FAILED(nsres)) + ERR("SetDisabled failed: %08x\n", nsres); + + return S_OK; } static HRESULT WINAPI HTMLInputElement_get_disabled(IHTMLInputElement *iface, VARIANT_BOOL *p) diff --git a/dlls/mshtml/htmlnode.c b/dlls/mshtml/htmlnode.c index afcf363c49b..ae2bff0a699 100644 --- a/dlls/mshtml/htmlnode.c +++ b/dlls/mshtml/htmlnode.c @@ -31,6 +31,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); +static HTMLDOMNode *get_node_obj(HTMLDocument*,IUnknown*); + typedef struct { DispatchEx dispex; const IHTMLDOMChildrenCollectionVtbl *lpIHTMLDOMChildrenCollectionVtbl; @@ -164,7 +166,7 @@ static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection TRACE("(%p)->(%ld %p)\n", This, index, ppItem); nsIDOMNodeList_GetLength(This->nslist, &length); - if(index < 0 || index > length) + if(index < 0 || index >= length) return E_INVALIDARG; nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode); @@ -178,6 +180,58 @@ static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection return S_OK; } +#define DISPID_CHILDCOL_0 MSHTML_DISPID_CUSTOM_MIN + +static HRESULT HTMLDOMChildrenCollection_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid) +{ + HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface); + WCHAR *ptr; + DWORD idx=0; + PRUint32 len = 0; + + for(ptr = name; *ptr && isdigitW(*ptr); ptr++) + idx = idx*10 + (*ptr-'0'); + if(*ptr) + return DISP_E_UNKNOWNNAME; + + nsIDOMNodeList_GetLength(This->nslist, &len); + if(idx >= len) + return DISP_E_UNKNOWNNAME; + + *dispid = DISPID_CHILDCOL_0 + idx; + TRACE("ret %x\n", *dispid); + return S_OK; +} + +static HRESULT HTMLDOMChildrenCollection_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface); + + TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller); + + switch(flags) { + case INVOKE_PROPERTYGET: { + IDispatch *disp = NULL; + HRESULT hres; + + hres = IHTMLDOMChildrenCollection_item(HTMLCHILDCOL(This), id - DISPID_CHILDCOL_0, &disp); + if(0&&FAILED(hres)) + return hres; + + V_VT(res) = VT_DISPATCH; + V_DISPATCH(res) = disp; + break; + } + + default: + FIXME("unimplemented flags %x\n", flags); + return E_NOTIMPL; + } + + return S_OK; +} + #undef HTMLCHILDCOL_THIS static const IHTMLDOMChildrenCollectionVtbl HTMLDOMChildrenCollectionVtbl = { @@ -197,8 +251,14 @@ static const tid_t HTMLDOMChildrenCollection_iface_tids[] = { IHTMLDOMChildrenCollection_tid, 0 }; + +static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = { + HTMLDOMChildrenCollection_get_dispid, + HTMLDOMChildrenCollection_invoke +}; + static dispex_static_data_t HTMLDOMChildrenCollection_dispex = { - NULL, + &HTMLDOMChildrenCollection_dispex_vtbl, DispDOMChildrenCollection_tid, NULL, HTMLDOMChildrenCollection_iface_tids @@ -310,6 +370,9 @@ static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, long *p) case COMMENT_NODE: *p = 8; break; + case DOCUMENT_NODE: + *p = 9; + break; default: /* * FIXME: @@ -326,15 +389,43 @@ static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, long *p) static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p) { HTMLDOMNode *This = HTMLDOMNODE_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + HTMLDOMNode *node; + nsIDOMNode *nsnode; + nsresult nsres; + + TRACE("(%p)->(%p)\n", This, p); + + nsres = nsIDOMNode_GetParentNode(This->nsnode, &nsnode); + if(NS_FAILED(nsres)) { + ERR("GetParentNode failed: %08x\n", nsres); + return E_FAIL; + } + + if(!nsnode) { + *p = NULL; + return S_OK; + } + + node = get_node(This->doc, nsnode, TRUE); + *p = HTMLDOMNODE(node); + IHTMLDOMNode_AddRef(*p); + return S_OK; } static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren) { HTMLDOMNode *This = HTMLDOMNODE_THIS(iface); - FIXME("(%p)->(%p)\n", This, fChildren); - return E_NOTIMPL; + PRBool has_child = FALSE; + nsresult nsres; + + TRACE("(%p)->(%p)\n", This, fChildren); + + nsres = nsIDOMNode_HasChildNodes(This->nsnode, &has_child); + if(NS_FAILED(nsres)) + ERR("HasChildNodes failed: %08x\n", nsres); + + *fChildren = has_child ? VARIANT_TRUE : VARIANT_FALSE; + return S_OK; } static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p) @@ -372,12 +463,30 @@ static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode return E_NOTIMPL; } -static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild, +static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *oldChild, IHTMLDOMNode **node) { HTMLDOMNode *This = HTMLDOMNODE_THIS(iface); - FIXME("(%p)->(%p %p)\n", This, newChild, node); - return E_NOTIMPL; + HTMLDOMNode *node_obj; + nsIDOMNode *nsnode; + nsresult nsres; + + TRACE("(%p)->(%p %p)\n", This, oldChild, node); + + node_obj = get_node_obj(This->doc, (IUnknown*)oldChild); + if(!node_obj) + return E_FAIL; + + nsres = nsIDOMNode_RemoveChild(This->nsnode, node_obj->nsnode, &nsnode); + if(NS_FAILED(nsres)) { + ERR("RemoveChild failed: %08x\n", nsres); + return E_FAIL; + } + + /* FIXME: Make sure that node != newChild */ + *node = HTMLDOMNODE(get_node(This->doc, nsnode, TRUE)); + IHTMLDOMNode_AddRef(*node); + return S_OK; } static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild, @@ -424,8 +533,26 @@ static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode IHTMLDOMNode **node) { HTMLDOMNode *This = HTMLDOMNODE_THIS(iface); - FIXME("(%p)->(%p %p)\n", This, newChild, node); - return E_NOTIMPL; + HTMLDOMNode *node_obj; + nsIDOMNode *nsnode; + nsresult nsres; + + TRACE("(%p)->(%p %p)\n", This, newChild, node); + + node_obj = get_node_obj(This->doc, (IUnknown*)newChild); + if(!node_obj) + return E_FAIL; + + nsres = nsIDOMNode_AppendChild(This->nsnode, node_obj->nsnode, &nsnode); + if(NS_FAILED(nsres)) { + ERR("AppendChild failed: %08x\n", nsres); + return E_FAIL; + } + + /* FIXME: Make sure that node != newChild */ + *node = HTMLDOMNODE(get_node(This->doc, nsnode, TRUE)); + IHTMLDOMNode_AddRef(*node); + return S_OK; } static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p) @@ -528,8 +655,19 @@ static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNo static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p) { HTMLDOMNode *This = HTMLDOMNODE_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsIDOMNode *nschild = NULL; + + TRACE("(%p)->(%p)\n", This, p); + + nsIDOMNode_GetLastChild(This->nsnode, &nschild); + if(nschild) { + *p = HTMLDOMNODE(get_node(This->doc, nschild, TRUE)); + IHTMLDOMNode_AddRef(*p); + }else { + *p = NULL; + } + + return S_OK; } static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p) @@ -769,6 +907,29 @@ HTMLDOMNode *get_node(HTMLDocument *This, nsIDOMNode *nsnode, BOOL create) return create_node(This, nsnode); } +/* + * FIXME + * We should use better way for getting node object (like private interface) + * or avoid it at all. + */ +static HTMLDOMNode *get_node_obj(HTMLDocument *This, IUnknown *iface) +{ + HTMLDOMNode *iter = This->nodes; + IHTMLDOMNode *node; + + IUnknown_QueryInterface(iface, &IID_IHTMLDOMNode, (void**)&node); + IHTMLDOMNode_Release(node); + + while(iter) { + if(HTMLDOMNODE(iter) == node) + return iter; + iter = iter->next; + } + + FIXME("Not found %p\n", iface); + return NULL; +} + void release_nodes(HTMLDocument *This) { HTMLDOMNode *iter, *next; diff --git a/dlls/mshtml/htmlselect.c b/dlls/mshtml/htmlselect.c index 1783bab6c73..9c7cf71dcea 100644 --- a/dlls/mshtml/htmlselect.c +++ b/dlls/mshtml/htmlselect.c @@ -68,16 +68,16 @@ static ULONG WINAPI HTMLSelectElement_Release(IHTMLSelectElement *iface) static HRESULT WINAPI HTMLSelectElement_GetTypeInfoCount(IHTMLSelectElement *iface, UINT *pctinfo) { HTMLSelectElement *This = HTMLSELECT_THIS(iface); - FIXME("(%p)->(%p)\n", This, pctinfo); - return E_NOTIMPL; + + return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->element.node.dispex), pctinfo); } static HRESULT WINAPI HTMLSelectElement_GetTypeInfo(IHTMLSelectElement *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) { HTMLSelectElement *This = HTMLSELECT_THIS(iface); - FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); - return E_NOTIMPL; + + return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->element.node.dispex), iTInfo, lcid, ppTInfo); } static HRESULT WINAPI HTMLSelectElement_GetIDsOfNames(IHTMLSelectElement *iface, REFIID riid, @@ -85,9 +85,8 @@ static HRESULT WINAPI HTMLSelectElement_GetIDsOfNames(IHTMLSelectElement *iface, LCID lcid, DISPID *rgDispId) { HTMLSelectElement *This = HTMLSELECT_THIS(iface); - FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, - lcid, rgDispId); - return E_NOTIMPL; + + return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->element.node.dispex), riid, rgszNames, cNames, lcid, rgDispId); } static HRESULT WINAPI HTMLSelectElement_Invoke(IHTMLSelectElement *iface, DISPID dispIdMember, @@ -95,9 +94,9 @@ static HRESULT WINAPI HTMLSelectElement_Invoke(IHTMLSelectElement *iface, DISPID VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { HTMLSelectElement *This = HTMLSELECT_THIS(iface); - FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), - lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - return E_NOTIMPL; + + return IDispatchEx_Invoke(DISPATCHEX(&This->element.node.dispex), dispIdMember, riid, lcid, + wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); } static HRESULT WINAPI HTMLSelectElement_put_size(IHTMLSelectElement *iface, long v) @@ -177,8 +176,10 @@ static HRESULT WINAPI HTMLSelectElement_get_options(IHTMLSelectElement *iface, I static HRESULT WINAPI HTMLSelectElement_put_onchange(IHTMLSelectElement *iface, VARIANT v) { HTMLSelectElement *This = HTMLSELECT_THIS(iface); - FIXME("(%p)->()\n", This); - return E_NOTIMPL; + + TRACE("(%p)->()\n", This); + + return set_node_event(&This->element.node, EVENTID_CHANGE, &v); } static HRESULT WINAPI HTMLSelectElement_get_onchange(IHTMLSelectElement *iface, VARIANT *p) @@ -221,15 +222,43 @@ static HRESULT WINAPI HTMLSelectElement_get_selectedIndex(IHTMLSelectElement *if static HRESULT WINAPI HTMLSelectElement_get_type(IHTMLSelectElement *iface, BSTR *p) { HTMLSelectElement *This = HTMLSELECT_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + const PRUnichar *type; + nsAString type_str; + nsresult nsres; + HRESULT hres = S_OK; + + TRACE("(%p)->(%p)\n", This, p); + + nsAString_Init(&type_str, NULL); + nsres = nsIDOMHTMLSelectElement_GetType(This->nsselect, &type_str); + if(NS_SUCCEEDED(nsres)) { + nsAString_GetData(&type_str, &type); + *p = *type ? SysAllocString(type) : NULL; + }else { + ERR("GetType failed: %08x\n", nsres); + hres = E_FAIL; + } + + nsAString_Finish(&type_str); + + return hres; } static HRESULT WINAPI HTMLSelectElement_put_value(IHTMLSelectElement *iface, BSTR v) { HTMLSelectElement *This = HTMLSELECT_THIS(iface); - FIXME("(%p)->(%s)\n", This, debugstr_w(v)); - return E_NOTIMPL; + nsAString value_str; + nsresult nsres; + + TRACE("(%p)->(%s)\n", This, debugstr_w(v)); + + nsAString_Init(&value_str, v); + nsres = nsIDOMHTMLSelectElement_SetValue(This->nsselect, &value_str); + nsAString_Finish(&value_str); + if(NS_FAILED(nsres)) + ERR("SetValue failed: %08x\n", nsres); + + return S_OK; } static HRESULT WINAPI HTMLSelectElement_get_value(IHTMLSelectElement *iface, BSTR *p) @@ -246,7 +275,7 @@ static HRESULT WINAPI HTMLSelectElement_get_value(IHTMLSelectElement *iface, BST nsres = nsIDOMHTMLSelectElement_GetValue(This->nsselect, &value_str); if(NS_SUCCEEDED(nsres)) { nsAString_GetData(&value_str, &value); - *p = SysAllocString(value); + *p = *value ? SysAllocString(value) : NULL; }else { ERR("GetValue failed: %08x\n", nsres); } diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index c42eb6ae3ff..7b2bf9e5cee 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -98,6 +98,14 @@ typedef enum { LAST_tid } tid_t; +typedef enum { + EVENTID_CHANGE, + EVENTID_CLICK, + EVENTID_KEYUP, + EVENTID_LOAD, + EVENTID_LAST +} eventid_t; + typedef struct dispex_data_t dispex_data_t; typedef struct dispex_dynamic_data_t dispex_dynamic_data_t; @@ -283,6 +291,7 @@ struct NSContainer { nsEventListener keypress_listener; nsEventListener load_listener; nsEventListener node_insert_listener; + nsEventListener htmlevent_listener; nsIWebBrowser *webbrowser; nsIWebNavigation *navigation; @@ -303,6 +312,8 @@ struct NSContainer { nsChannelBSC *bscallback; /* hack */ HWND reset_focus; /* hack */ + + BOOL event_vector[EVENTID_LAST]; }; typedef struct { @@ -490,16 +501,14 @@ nsIWritableVariant *create_nsvariant(void); void nsnode_to_nsstring(nsIDOMNode*,nsAString*); void get_editor_controller(NSContainer*); void init_nsevents(NSContainer*); +void add_nsevent_listener(NSContainer*,LPCWSTR); nsresult get_nsinterface(nsISupports*,REFIID,void**); -typedef enum { - EVENTID_LOAD, - EVENTID_LAST -} eventid_t; - void check_event_attr(HTMLDocument*,nsIDOMElement*); void release_event_target(event_target_t*); void fire_event(HTMLDocument*,eventid_t,nsIDOMNode*); +HRESULT set_node_event(HTMLDOMNode*,eventid_t,VARIANT*); +eventid_t str_to_eid(LPCWSTR); void set_document_bscallback(HTMLDocument*,nsChannelBSC*); void set_current_mon(HTMLDocument*,IMoniker*); diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index cec359842bd..73aba168a39 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -1643,7 +1643,7 @@ NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent) if(!load_gecko(FALSE)) return NULL; - ret = heap_alloc(sizeof(NSContainer)); + ret = heap_alloc_zero(sizeof(NSContainer)); ret->lpWebBrowserChromeVtbl = &nsWebBrowserChromeVtbl; ret->lpContextMenuListenerVtbl = &nsContextMenuListenerVtbl; @@ -1656,11 +1656,6 @@ NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent) ret->doc = doc; ret->ref = 1; - ret->bscallback = NULL; - ret->content_listener = NULL; - ret->editor_controller = NULL; - ret->editor = NULL; - ret->reset_focus = NULL; nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_WEBBROWSER_CONTRACTID, NULL, &IID_nsIWebBrowser, (void**)&ret->webbrowser); diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c index 5b72a2d9f79..d0f5079a666 100644 --- a/dlls/mshtml/nsevents.c +++ b/dlls/mshtml/nsevents.c @@ -211,6 +211,42 @@ static nsresult NSAPI handle_node_insert(nsIDOMEventListener *iface, nsIDOMEvent return NS_OK; } +static nsresult NSAPI handle_htmlevent(nsIDOMEventListener *iface, nsIDOMEvent *event) +{ + NSContainer *This = NSEVENTLIST_THIS(iface)->This; + const PRUnichar *type; + nsIDOMEventTarget *event_target; + nsIDOMNode *nsnode; + nsAString type_str; + eventid_t eid; + nsresult nsres; + + nsAString_Init(&type_str, NULL); + nsIDOMEvent_GetType(event, &type_str); + nsAString_GetData(&type_str, &type); + eid = str_to_eid(type); + nsAString_Finish(&type_str); + + nsres = nsIDOMEvent_GetTarget(event, &event_target); + if(NS_FAILED(nsres) || !event_target) { + ERR("GetEventTarget failed: %08x\n", nsres); + return NS_OK; + } + + nsres = nsIDOMEventTarget_QueryInterface(event_target, &IID_nsIDOMNode, (void**)&nsnode); + nsIDOMEventTarget_Release(event_target); + if(NS_FAILED(nsres)) { + ERR("Could not get nsIDOMNode: %08x\n", nsres); + return NS_OK; + } + + fire_event(This->doc, eid, nsnode); + + nsIDOMNode_Release(nsnode); + + return NS_OK; +} + #undef NSEVENTLIST_THIS #define EVENTLISTENER_VTBL(handler) \ @@ -226,6 +262,7 @@ static const nsIDOMEventListenerVtbl focus_vtbl = EVENTLISTENER_VTBL(handle_ static const nsIDOMEventListenerVtbl keypress_vtbl = EVENTLISTENER_VTBL(handle_keypress); static const nsIDOMEventListenerVtbl load_vtbl = EVENTLISTENER_VTBL(handle_load); static const nsIDOMEventListenerVtbl node_insert_vtbl = EVENTLISTENER_VTBL(handle_node_insert); +static const nsIDOMEventListenerVtbl htmlevent_vtbl = EVENTLISTENER_VTBL(handle_htmlevent); static void init_event(nsIDOMEventTarget *target, const PRUnichar *type, nsIDOMEventListener *listener, BOOL capture) @@ -248,6 +285,29 @@ static void init_listener(nsEventListener *This, NSContainer *container, This->This = container; } +void add_nsevent_listener(NSContainer *container, LPCWSTR type) +{ + nsIDOMWindow *dom_window; + nsIDOMEventTarget *target; + nsresult nsres; + + nsres = nsIWebBrowser_GetContentDOMWindow(container->webbrowser, &dom_window); + if(NS_FAILED(nsres)) { + ERR("GetContentDOMWindow failed: %08x\n", nsres); + return; + } + + nsres = nsIDOMWindow_QueryInterface(dom_window, &IID_nsIDOMEventTarget, (void**)&target); + nsIDOMWindow_Release(dom_window); + if(NS_FAILED(nsres)) { + ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres); + return; + } + + init_event(target, type, NSEVENTLIST(&container->htmlevent_listener), TRUE); + nsIDOMEventTarget_Release(target); +} + void init_nsevents(NSContainer *This) { nsIDOMWindow *dom_window; @@ -266,6 +326,7 @@ void init_nsevents(NSContainer *This) init_listener(&This->keypress_listener, This, &keypress_vtbl); init_listener(&This->load_listener, This, &load_vtbl); init_listener(&This->node_insert_listener, This, &node_insert_vtbl); + init_listener(&This->htmlevent_listener, This, &htmlevent_vtbl); nsres = nsIWebBrowser_GetContentDOMWindow(This->webbrowser, &dom_window); if(NS_FAILED(nsres)) { diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl index 62bead1d7e0..42e6eb00632 100644 --- a/dlls/mshtml/nsiface.idl +++ b/dlls/mshtml/nsiface.idl @@ -1297,6 +1297,39 @@ interface nsIDOMHTMLScriptElement : nsIDOMHTMLElement [ object, + uuid(a6cf90ab-15b3-11d2-932e-00805f8add32), + local +] +interface nsIDOMHTMLImageElement : nsIDOMHTMLElement +{ + nsresult GetName(nsAString *aName); + nsresult SetName(const nsAString *aName); + nsresult GetAlign(nsAString *aAlign); + nsresult SetAlign(const nsAString *aAlign); + nsresult GetAlt(nsAString *aAlt); + nsresult SetAlt(const nsAString *aAlt); + nsresult GetBorder(nsAString *aBorder); + nsresult SetBorder(const nsAString *aBorder); + nsresult GetHeight(PRInt32 *aHeight); + nsresult SetHeight(PRInt32 aHeight); + nsresult GetHspace(PRInt32 *aHspace); + nsresult SetHspace(PRInt32 aHspace); + nsresult GetIsMap(PRBool *aIsMap); + nsresult SetIsMap(PRBool aIsMap); + nsresult GetLongDesc(nsAString *aLongDesc); + nsresult SetLongDesc(const nsAString *aLongDesc); + nsresult GetSrc(nsAString *aSrc); + nsresult SetSrc(const nsAString *aSrc); + nsresult GetUseMap(nsAString *aUseMap); + nsresult SetUseMap(const nsAString *aUseMap); + nsresult GetVspace(PRInt32 *aVspace); + nsresult SetVspace(PRInt32 aVspace); + nsresult GetWidth(PRInt32 *aWidth); + nsresult SetWidth(PRInt32 aWidth); +} + +[ + object, uuid(94928ab3-8b63-11d3-989d-001083010e9b), local /* FROZEN */ diff --git a/dlls/mshtml/nsio.c b/dlls/mshtml/nsio.c index 53ad33e334e..f23254ab195 100644 --- a/dlls/mshtml/nsio.c +++ b/dlls/mshtml/nsio.c @@ -2040,7 +2040,6 @@ static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString * const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval) { const char *spec = NULL; - nsACString spec_str; NSContainer *nscontainer = NULL; nsIURI *uri = NULL; LPCWSTR base_wine_url = NULL; @@ -2078,9 +2077,7 @@ static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString * nsACString_Finish(&base_uri_str); } - nsACString_Init(&spec_str, spec); - nsres = nsIIOService_NewURI(nsio, &spec_str, aOriginCharset, aBaseURI, &uri); - nsACString_Finish(&spec_str); + nsres = nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, &uri); if(NS_FAILED(nsres)) TRACE("NewURI failed: %08x\n", nsres); diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index 8611a41db0f..d06ad4c6462 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -42,13 +42,13 @@ static const char elem_test_str[] = "test" "text test" "link" - "" - "" + "" + "" "" "
" "" "" - "" ""; static const char indent_test_str[] = "testabc
123"; @@ -475,6 +475,19 @@ static void _test_elem_attr(unsigned line, IHTMLElement *elem, LPCWSTR name, LPC VariantClear(&value); } +#define test_elem_offset(u) _test_elem_offset(__LINE__,u) +static void _test_elem_offset(unsigned line, IUnknown *unk) +{ + IHTMLElement *elem = _get_elem_iface(line, unk); + long l; + HRESULT hres; + + hres = IHTMLElement_get_offsetTop(elem, &l); + ok_(__FILE__,line) (hres == S_OK, "get_offsetTop failed: %08x\n", hres); + + IHTMLElement_Release(elem); +} + static void test_doc_elem(IHTMLDocument2 *doc) { IHTMLElement *elem; @@ -630,6 +643,43 @@ static void _test_select_put_selidx(unsigned line, IHTMLSelectElement *select, l _test_select_selidx(line, select, index); } +#define test_select_value(s,v) _test_select_value(__LINE__,s,v) +static void _test_select_value(unsigned line, IHTMLSelectElement *select, const char *exval) +{ + BSTR val; + HRESULT hres; + + hres = IHTMLSelectElement_get_value(select, &val); + ok_(__FILE__,line) (hres == S_OK, "get_value failed: %08x\n", hres); + if(exval) + ok_(__FILE__,line) (!strcmp_wa(val, exval), "unexpected value %s\n", dbgstr_w(val)); + else + ok_(__FILE__,line) (val == NULL, "val=%s, expected NULL\n", dbgstr_w(val)); +} + +#define test_select_set_value(s,v) _test_select_set_value(__LINE__,s,v) +static void _test_select_set_value(unsigned line, IHTMLSelectElement *select, const char *val) +{ + BSTR bstr; + HRESULT hres; + + bstr = a2bstr(val); + hres = IHTMLSelectElement_put_value(select, bstr); + SysFreeString(bstr); + ok_(__FILE__,line) (hres == S_OK, "put_value failed: %08x\n", hres); +} + +#define test_select_type(s,t) _test_select_type(__LINE__,s,t) +static void _test_select_type(unsigned line, IHTMLSelectElement *select, const char *extype) +{ + BSTR type; + HRESULT hres; + + hres = IHTMLSelectElement_get_type(select, &type); + ok_(__FILE__,line) (hres == S_OK, "get_type failed: %08x\n", hres); + ok_(__FILE__,line) (!strcmp_wa(type, extype), "type=%s, expected %s\n", dbgstr_w(type), extype); +} + #define test_range_text(r,t) _test_range_text(__LINE__,r,t) static void _test_range_text(unsigned line, IHTMLTxtRange *range, const char *extext) { @@ -769,15 +819,19 @@ static void _test_range_parent(unsigned line, IHTMLTxtRange *range, elem_type_t } #define test_elem_collection(c,t,l) _test_elem_collection(__LINE__,c,t,l) -static void _test_elem_collection(unsigned line, IHTMLElementCollection *col, +static void _test_elem_collection(unsigned line, IUnknown *unk, const elem_type_t *elem_types, long exlen) { + IHTMLElementCollection *col; long len; DWORD i; VARIANT name, index; IDispatch *disp; HRESULT hres; + hres = IUnknown_QueryInterface(unk, &IID_IHTMLElementCollection, (void**)&col); + ok(hres == S_OK, "Could not get IHTMLElementCollection: %08x\n", hres); + test_disp((IUnknown*)col, &DIID_DispHTMLElementCollection); hres = IHTMLElementCollection_get_length(col, &len); @@ -814,6 +868,8 @@ static void _test_elem_collection(unsigned line, IHTMLElementCollection *col, hres = IHTMLElementCollection_item(col, name, index, &disp); ok_(__FILE__,line) (hres == E_INVALIDARG, "item failed: %08x, expected E_INVALIDARG\n", hres); ok_(__FILE__,line) (disp == NULL, "disp != NULL\n"); + + IHTMLElementCollection_Release(col); } #define get_first_child(n) _get_first_child(__LINE__,n) @@ -830,6 +886,34 @@ static IHTMLDOMNode *_get_first_child(unsigned line, IUnknown *unk) return child; } +#define test_node_has_child(u,b) _test_node_has_child(__LINE__,u,b) +static void _test_node_has_child(unsigned line, IUnknown *unk, VARIANT_BOOL exb) +{ + IHTMLDOMNode *node = _get_node_iface(line, unk); + VARIANT_BOOL b = 0xdead; + HRESULT hres; + + hres = IHTMLDOMNode_hasChildNodes(node, &b); + ok_(__FILE__,line) (hres == S_OK, "hasChildNodes failed: %08x\n", hres); + ok_(__FILE__,line) (b == exb, "hasChildNodes=%x, expected %x\n", b, exb); + + IHTMLDOMNode_Release(node); +} + +#define test_node_get_parent(u) _test_node_get_parent(__LINE__,u) +static IHTMLDOMNode *_test_node_get_parent(unsigned line, IUnknown *unk) +{ + IHTMLDOMNode *node = _get_node_iface(line, unk); + IHTMLDOMNode *parent; + HRESULT hres; + + hres = IHTMLDOMNode_get_parentNode(node, &parent); + IHTMLDOMNode_Release(node); + ok_(__FILE__,line) (hres == S_OK, "get_parentNode failed: %08x\n", hres); + + return parent; +} + #define get_node_type(n) _get_node_type(__LINE__,n) static long _get_node_type(unsigned line, IUnknown *unk) { @@ -845,6 +929,23 @@ static long _get_node_type(unsigned line, IUnknown *unk) return type; } +#define test_img_set_src(u,s) _test_img_set_src(__LINE__,u,s) +static void _test_img_set_src(unsigned line, IUnknown *unk, const char *src) +{ + IHTMLImgElement *img; + BSTR tmp; + HRESULT hres; + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLImgElement, (void**)&img); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLImgElement: %08x\n", hres); + + tmp = a2bstr(src); + hres = IHTMLImgElement_put_src(img, tmp); + IHTMLImgElement_Release(img); + SysFreeString(tmp); + ok_(__FILE__,line) (hres == S_OK, "put_src failed: %08x\n", hres); +} + #define test_input_get_disabled(i,b) _test_input_get_disabled(__LINE__,i,b) static void _test_input_get_disabled(unsigned line, IHTMLInputElement *input, VARIANT_BOOL exb) { @@ -856,6 +957,17 @@ static void _test_input_get_disabled(unsigned line, IHTMLInputElement *input, VA ok_(__FILE__,line) (disabled == exb, "disabled=%x, expected %x\n", disabled, exb); } +#define test_input_set_disabled(i,b) _test_input_set_disabled(__LINE__,i,b) +static void _test_input_set_disabled(unsigned line, IHTMLInputElement *input, VARIANT_BOOL b) +{ + HRESULT hres; + + hres = IHTMLInputElement_put_disabled(input, b); + ok_(__FILE__,line) (hres == S_OK, "get_disabled failed: %08x\n", hres); + + _test_input_get_disabled(line, input, b); +} + #define test_input_value(o,t) _test_input_value(__LINE__,o,t) static void _test_input_value(unsigned line, IUnknown *unk, const char *exval) { @@ -918,6 +1030,65 @@ static IHTMLDOMChildrenCollection *_get_child_nodes(unsigned line, IUnknown *unk return col; } +#define test_elem_class(u,c) _test_elem_class(__LINE__,u,c) +static void _test_elem_class(unsigned line, IUnknown *unk, const char *exclass) +{ + IHTMLElement *elem = _get_elem_iface(line, unk); + BSTR class = (void*)0xdeadbeef; + HRESULT hres; + + hres = IHTMLElement_get_className(elem, &class); + IHTMLElement_Release(elem); + ok_(__FILE__,line) (hres == S_OK, "get_className failed: %08x\n", hres); + if(exclass) + ok_(__FILE__,line) (!strcmp_wa(class, exclass), "unexpected className %s\n", dbgstr_w(class)); + else + ok_(__FILE__,line) (!class, "class != NULL\n"); + SysFreeString(class); +} + +#define test_elem_tabindex(u,i) _test_elem_tabindex(__LINE__,u,i) +static void _test_elem_tabindex(unsigned line, IUnknown *unk, short exindex) +{ + IHTMLElement2 *elem2 = _get_elem2_iface(line, unk); + short index = -3; + HRESULT hres; + + hres = IHTMLElement2_get_tabIndex(elem2, &index); + IHTMLElement2_Release(elem2); + ok_(__FILE__,line) (hres == S_OK, "get_tabIndex failed: %08x\n", hres); + ok_(__FILE__,line) (index == exindex, "unexpected index %d\n", index); +} + +#define test_elem_set_tabindex(u,i) _test_elem_set_tabindex(__LINE__,u,i) +static void _test_elem_set_tabindex(unsigned line, IUnknown *unk, short index) +{ + IHTMLElement2 *elem2 = _get_elem2_iface(line, unk); + HRESULT hres; + + hres = IHTMLElement2_put_tabIndex(elem2, index); + IHTMLElement2_Release(elem2); + ok_(__FILE__,line) (hres == S_OK, "get_tabIndex failed: %08x\n", hres); + + _test_elem_tabindex(line, unk, index); +} + +#define test_elem_set_class(u,c) _test_elem_set_class(__LINE__,u,c) +static void _test_elem_set_class(unsigned line, IUnknown *unk, const char *class) +{ + IHTMLElement *elem = _get_elem_iface(line, unk); + BSTR tmp; + HRESULT hres; + + tmp = class ? a2bstr(class) : NULL; + hres = IHTMLElement_put_className(elem, tmp); + IHTMLElement_Release(elem); + ok_(__FILE__,line) (hres == S_OK, "put_className failed: %08x\n", hres); + SysFreeString(tmp); + + _test_elem_class(line, unk, class); +} + #define get_child_item(c,i) _get_child_item(__LINE__,c,i) static IHTMLDOMNode *_get_child_item(unsigned line, IHTMLDOMChildrenCollection *col, long idx) { @@ -968,6 +1139,39 @@ static void _test_elem_put_id(unsigned line, IUnknown *unk, const char *new_id) _test_elem_id(line, unk, new_id); } +#define test_elem_title(u,t) _test_elem_title(__LINE__,u,t) +static void _test_elem_title(unsigned line, IUnknown *unk, const char *extitle) +{ + IHTMLElement *elem = _get_elem_iface(line, unk); + BSTR title; + HRESULT hres; + + hres = IHTMLElement_get_title(elem, &title); + IHTMLElement_Release(elem); + ok_(__FILE__,line) (hres == S_OK, "get_title failed: %08x\n", hres); + if(extitle) + ok_(__FILE__,line) (!strcmp_wa(title, extitle), "unexpected title %s\n", dbgstr_w(title)); + else + ok_(__FILE__,line) (!title, "title=%s, expected NULL\n", dbgstr_w(title)); + + SysFreeString(title); +} + +#define test_elem_set_title(u,t) _test_elem_set_title(__LINE__,u,t) +static void _test_elem_set_title(unsigned line, IUnknown *unk, const char *title) +{ + IHTMLElement *elem = _get_elem_iface(line, unk); + BSTR tmp; + HRESULT hres; + + tmp = a2bstr(title); + hres = IHTMLElement_put_title(elem, tmp); + ok_(__FILE__,line) (hres == S_OK, "get_title failed: %08x\n", hres); + + IHTMLElement_Release(elem); + SysFreeString(tmp); +} + #define test_node_get_value_str(u,e) _test_node_get_value_str(__LINE__,u,e) static void _test_node_get_value_str(unsigned line, IUnknown *unk, const char *exval) { @@ -1035,10 +1239,64 @@ static IHTMLElement *_test_create_elem(unsigned line, IHTMLDocument2 *doc, const return elem; } +#define test_create_text(d,t) _test_create_text(__LINE__,d,t) +static IHTMLDOMNode *_test_create_text(unsigned line, IHTMLDocument2 *doc, const char *text) +{ + IHTMLDocument3 *doc3; + IHTMLDOMNode *node = NULL; + BSTR tmp; + HRESULT hres; + + hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDocument3: %08x\n", hres); + + tmp = a2bstr(text); + hres = IHTMLDocument3_createTextNode(doc3, tmp, &node); + IHTMLDocument3_Release(doc3); + ok_(__FILE__,line) (hres == S_OK, "createElement failed: %08x\n", hres); + ok_(__FILE__,line) (node != NULL, "node == NULL\n"); + + return node; +} + +#define test_node_append_child(n,c) _test_node_append_child(__LINE__,n,c) +static IHTMLDOMNode *_test_node_append_child(unsigned line, IUnknown *node_unk, IUnknown *child_unk) +{ + IHTMLDOMNode *node = _get_node_iface(line, node_unk); + IHTMLDOMNode *child = _get_node_iface(line, child_unk); + IHTMLDOMNode *new_child = NULL; + HRESULT hres; + + hres = IHTMLDOMNode_appendChild(node, child, &new_child); + ok_(__FILE__,line) (hres == S_OK, "appendChild failed: %08x\n", hres); + ok_(__FILE__,line) (new_child != NULL, "new_child == NULL\n"); + /* TODO ok_(__FILE__,line) (new_child != child, "new_child == child\n"); */ + + IHTMLDOMNode_Release(node); + IHTMLDOMNode_Release(child); + + return new_child; +} + +#define test_node_remove_child(n,c) _test_node_remove_child(__LINE__,n,c) +static void _test_node_remove_child(unsigned line, IUnknown *unk, IHTMLDOMNode *child) +{ + IHTMLDOMNode *node = _get_node_iface(line, unk); + IHTMLDOMNode *new_node = NULL; + HRESULT hres; + + hres = IHTMLDOMNode_removeChild(node, child, &new_node); + ok_(__FILE__,line) (hres == S_OK, "appendChild failed: %08x\n", hres); + ok_(__FILE__,line) (new_node != NULL, "new_node == NULL\n"); + /* TODO ok_(__FILE__,line) (new_node != child, "new_node == child\n"); */ + + IHTMLDOMNode_Release(node); + IHTMLDOMNode_Release(new_node); +} + static void test_elem_col_item(IHTMLElementCollection *col, LPCWSTR n, const elem_type_t *elem_types, long len) { - IHTMLElementCollection *elcol; IDispatch *disp; VARIANT name, index; DWORD i; @@ -1051,15 +1309,12 @@ static void test_elem_col_item(IHTMLElementCollection *col, LPCWSTR n, hres = IHTMLElementCollection_item(col, name, index, &disp); ok(hres == S_OK, "item failed: %08x\n", hres); - hres = IDispatch_QueryInterface(disp, &IID_IHTMLElementCollection, (void**)&elcol); + test_elem_collection((IUnknown*)disp, elem_types, len); IDispatch_Release(disp); ok(hres == S_OK, "Could not get IHTMLElementCollection interface: %08x\n", hres); if(hres != S_OK) goto cleanup; - test_elem_collection(elcol, elem_types, len); - IHTMLElementCollection_Release(elcol); - V_VT(&index) = VT_I4; for(i=0; idb, query, &view); + if (r == ERROR_SUCCESS) + { + MSI_IterateRecords(view, NULL, ITERATE_PublishIcon, package); + msiobj_release(&view->hdr); + } + + return ERROR_SUCCESS; +} + +static UINT msi_publish_sourcelist(MSIPACKAGE *package, HKEY hkey) +{ + UINT r; + HKEY source; + LPWSTR buffer; + MSIMEDIADISK *disk; + MSISOURCELISTINFO *info; + + static const WCHAR szEmpty[] = {0}; + static const WCHAR szSourceList[] = {'S','o','u','r','c','e','L','i','s','t',0}; + + r = RegCreateKeyW(hkey, szSourceList, &source); + if (r != ERROR_SUCCESS) + return r; + + RegCloseKey(source); + + buffer = strrchrW(package->PackagePath, '\\') + 1; + r = MsiSourceListSetInfoW(package->ProductCode, NULL, + package->Context, MSICODE_PRODUCT, + INSTALLPROPERTY_PACKAGENAMEW, buffer); + if (r != ERROR_SUCCESS) + return r; + + r = MsiSourceListSetInfoW(package->ProductCode, NULL, + package->Context, MSICODE_PRODUCT, + INSTALLPROPERTY_MEDIAPACKAGEPATHW, szEmpty); + if (r != ERROR_SUCCESS) + return r; + + r = MsiSourceListSetInfoW(package->ProductCode, NULL, + package->Context, MSICODE_PRODUCT, + INSTALLPROPERTY_DISKPROMPTW, szEmpty); + if (r != ERROR_SUCCESS) + return r; + + LIST_FOR_EACH_ENTRY(info, &package->sourcelist_info, MSISOURCELISTINFO, entry) + { + if (!lstrcmpW(info->property, INSTALLPROPERTY_LASTUSEDSOURCEW)) + msi_set_last_used_source(package->ProductCode, NULL, info->context, + info->options, info->value); + else + MsiSourceListSetInfoW(package->ProductCode, NULL, + info->context, info->options, + info->property, info->value); + } + + LIST_FOR_EACH_ENTRY(disk, &package->sourcelist_media, MSIMEDIADISK, entry) + { + MsiSourceListAddMediaDiskW(package->ProductCode, NULL, + disk->context, disk->options, + disk->disk_id, disk->volume_label, disk->disk_prompt); + } + + return ERROR_SUCCESS; +} + +static UINT msi_publish_product_properties(MSIPACKAGE *package, HKEY hkey) +{ + MSIHANDLE hdb, suminfo; + WCHAR guids[MAX_PATH]; + WCHAR packcode[SQUISH_GUID_SIZE]; + LPWSTR buffer; + LPWSTR ptr; + DWORD langid; + DWORD size; + UINT r; + + static const WCHAR szProductLanguage[] = + {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0}; + static const WCHAR szARPProductIcon[] = + {'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0}; + static const WCHAR szProductVersion[] = + {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0}; + static const WCHAR szAssignment[] = + {'A','s','s','i','g','n','m','e','n','t',0}; + static const WCHAR szAdvertiseFlags[] = + {'A','d','v','e','r','t','i','s','e','F','l','a','g','s',0}; + static const WCHAR szClients[] = + {'C','l','i','e','n','t','s',0}; + static const WCHAR szColon[] = {':',0}; + + buffer = msi_dup_property(package, INSTALLPROPERTY_PRODUCTNAMEW); + msi_reg_set_val_str(hkey, INSTALLPROPERTY_PRODUCTNAMEW, buffer); + msi_free(buffer); + + langid = msi_get_property_int(package, szProductLanguage, 0); + msi_reg_set_val_dword(hkey, INSTALLPROPERTY_LANGUAGEW, langid); + + ptr = strrchrW(package->PackagePath, '\\' ) + 1; + msi_reg_set_val_str(hkey, INSTALLPROPERTY_PACKAGENAMEW, ptr); + + /* FIXME */ + msi_reg_set_val_dword(hkey, INSTALLPROPERTY_AUTHORIZED_LUA_APPW, 0); + + buffer = msi_dup_property(package, szARPProductIcon); + if (buffer) + { + LPWSTR path = build_icon_path(package,buffer); + msi_reg_set_val_str(hkey, INSTALLPROPERTY_PRODUCTICONW, path); + msi_free(path); + msi_free(buffer); + } + + buffer = msi_dup_property(package, szProductVersion); + if (buffer) + { + DWORD verdword = msi_version_str_to_dword(buffer); + msi_reg_set_val_dword(hkey, INSTALLPROPERTY_VERSIONW, verdword); + msi_free(buffer); + } + + msi_reg_set_val_dword(hkey, szAssignment, 0); + msi_reg_set_val_dword(hkey, szAdvertiseFlags, 0x184); + msi_reg_set_val_dword(hkey, INSTALLPROPERTY_INSTANCETYPEW, 0); + msi_reg_set_val_str(hkey, szClients, szColon); + + hdb = alloc_msihandle(&package->db->hdr); + if (!hdb) + return ERROR_NOT_ENOUGH_MEMORY; + + r = MsiGetSummaryInformationW(hdb, NULL, 0, &suminfo); + MsiCloseHandle(hdb); + if (r != ERROR_SUCCESS) + goto done; + + size = MAX_PATH; + r = MsiSummaryInfoGetPropertyW(suminfo, PID_REVNUMBER, NULL, NULL, + NULL, guids, &size); + if (r != ERROR_SUCCESS) + goto done; + + ptr = strchrW(guids, ';'); + if (ptr) *ptr = 0; + squash_guid(guids, packcode); + msi_reg_set_val_str(hkey, INSTALLPROPERTY_PACKAGECODEW, packcode); + +done: + MsiCloseHandle(suminfo); + return ERROR_SUCCESS; +} + +static UINT msi_publish_upgrade_code(MSIPACKAGE *package) +{ + UINT r; + HKEY hkey; + LPWSTR upgrade; + WCHAR squashed_pc[SQUISH_GUID_SIZE]; + + static const WCHAR szUpgradeCode[] = + {'U','p','g','r','a','d','e','C','o','d','e',0}; + + upgrade = msi_dup_property(package, szUpgradeCode); + if (!upgrade) + return ERROR_SUCCESS; + + if (package->Context == MSIINSTALLCONTEXT_MACHINE) + { + r = MSIREG_OpenClassesUpgradeCodesKey(upgrade, &hkey, TRUE); + if (r != ERROR_SUCCESS) + goto done; + } + else + { + r = MSIREG_OpenUserUpgradeCodesKey(upgrade, &hkey, TRUE); + if (r != ERROR_SUCCESS) + goto done; + } + + squash_guid(package->ProductCode, squashed_pc); + msi_reg_set_val_str(hkey, squashed_pc, NULL); + + RegCloseKey(hkey); + +done: + msi_free(upgrade); + return r; +} + static BOOL msi_check_publish(MSIPACKAGE *package) { MSIFEATURE *feature; @@ -3333,6 +3531,19 @@ static BOOL msi_check_publish(MSIPACKAGE *package) return FALSE; } +static BOOL msi_check_unpublish(MSIPACKAGE *package) +{ + MSIFEATURE *feature; + + LIST_FOR_EACH_ENTRY(feature, &package->features, MSIFEATURE, entry) + { + if (feature->ActionRequest != INSTALLSTATE_ABSENT) + return FALSE; + } + + return TRUE; +} + /* * 99% of the work done here is only done for * advertised installs. However this is where the @@ -3342,191 +3553,51 @@ static BOOL msi_check_publish(MSIPACKAGE *package) static UINT ACTION_PublishProduct(MSIPACKAGE *package) { UINT rc; - LPWSTR packname; - MSIQUERY * view; - MSISOURCELISTINFO *info; - MSIMEDIADISK *disk; - static const WCHAR Query[]= - {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', - '`','I','c','o','n','`',0}; - /* for registry stuff */ - HKEY hkey=0; HKEY hukey=0; - HKEY hudkey=0, props=0; - HKEY source; - static const WCHAR szProductLanguage[] = - {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0}; - static const WCHAR szARPProductIcon[] = - {'A','R','P','P','R','O','D','U','C','T','I','C','O','N',0}; - static const WCHAR szProductVersion[] = - {'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0}; - static const WCHAR szSourceList[] = - {'S','o','u','r','c','e','L','i','s','t',0}; - static const WCHAR szEmpty[] = {0}; - DWORD langid; - LPWSTR buffer; - DWORD size; - MSIHANDLE hDb, hSumInfo; + HKEY hudkey=0; /* FIXME: also need to publish if the product is in advertise mode */ if (!msi_check_publish(package)) return ERROR_SUCCESS; - /* write out icon files */ - - rc = MSI_DatabaseOpenViewW(package->db, Query, &view); - if (rc == ERROR_SUCCESS) - { - MSI_IterateRecords(view, NULL, ITERATE_PublishProduct, package); - msiobj_release(&view->hdr); - } - - /* ok there is a lot more done here but i need to figure out what */ - if (package->Context == MSIINSTALLCONTEXT_MACHINE) { rc = MSIREG_OpenLocalClassesProductKey(package->ProductCode, &hukey, TRUE); if (rc != ERROR_SUCCESS) goto end; - rc = MSIREG_OpenLocalSystemInstallProps(package->ProductCode, &props, TRUE); + rc = MSIREG_OpenLocalUserDataProductKey(package->ProductCode, &hudkey, TRUE); if (rc != ERROR_SUCCESS) goto end; } else { - rc = MSIREG_OpenProductsKey(package->ProductCode,&hkey,TRUE); + rc = MSIREG_OpenUserProductsKey(package->ProductCode, &hukey, TRUE); if (rc != ERROR_SUCCESS) goto end; - rc = MSIREG_OpenUserProductsKey(package->ProductCode,&hukey,TRUE); - if (rc != ERROR_SUCCESS) - goto end; - - rc = MSIREG_OpenCurrentUserInstallProps(package->ProductCode, &props, TRUE); + rc = MSIREG_OpenUserDataProductKey(package->ProductCode, &hudkey, TRUE); if (rc != ERROR_SUCCESS) goto end; } - rc = RegCreateKeyW(hukey, szSourceList, &source); + rc = msi_publish_upgrade_code(package); if (rc != ERROR_SUCCESS) goto end; - RegCloseKey(source); - - rc = MSIREG_OpenUserDataProductKey(package->ProductCode,&hudkey,TRUE); + rc = msi_publish_product_properties(package, hukey); if (rc != ERROR_SUCCESS) goto end; - buffer = msi_dup_property( package, INSTALLPROPERTY_PRODUCTNAMEW ); - msi_reg_set_val_str( hukey, INSTALLPROPERTY_PRODUCTNAMEW, buffer ); - msi_free(buffer); - - langid = msi_get_property_int( package, szProductLanguage, 0 ); - msi_reg_set_val_dword( hukey, INSTALLPROPERTY_LANGUAGEW, langid ); - - packname = strrchrW( package->PackagePath, '\\' ) + 1; - msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGENAMEW, packname ); - - /* FIXME */ - msi_reg_set_val_dword( hukey, INSTALLPROPERTY_AUTHORIZED_LUA_APPW, 0 ); - msi_reg_set_val_dword( props, INSTALLPROPERTY_INSTANCETYPEW, 0 ); - - buffer = msi_dup_property( package, szARPProductIcon ); - if (buffer) - { - LPWSTR path = build_icon_path(package,buffer); - msi_reg_set_val_str( hukey, INSTALLPROPERTY_PRODUCTICONW, path ); - msi_free( path ); - } - msi_free(buffer); - - buffer = msi_dup_property( package, szProductVersion ); - if (buffer) - { - DWORD verdword = msi_version_str_to_dword(buffer); - msi_reg_set_val_dword( hukey, INSTALLPROPERTY_VERSIONW, verdword ); - } - msi_free(buffer); - - buffer = strrchrW( package->PackagePath, '\\') + 1; - rc = MsiSourceListSetInfoW( package->ProductCode, NULL, - package->Context, MSICODE_PRODUCT, - INSTALLPROPERTY_PACKAGENAMEW, buffer ); - if (rc != ERROR_SUCCESS) - goto end; - - rc = MsiSourceListSetInfoW( package->ProductCode, NULL, - package->Context, MSICODE_PRODUCT, - INSTALLPROPERTY_MEDIAPACKAGEPATHW, szEmpty ); - if (rc != ERROR_SUCCESS) - goto end; - - rc = MsiSourceListSetInfoW( package->ProductCode, NULL, - package->Context, MSICODE_PRODUCT, - INSTALLPROPERTY_DISKPROMPTW, szEmpty ); + rc = msi_publish_sourcelist(package, hukey); if (rc != ERROR_SUCCESS) goto end; - /* FIXME: Need to write more keys to the user registry */ - - hDb= alloc_msihandle( &package->db->hdr ); - if (!hDb) { - rc = ERROR_NOT_ENOUGH_MEMORY; - goto end; - } - rc = MsiGetSummaryInformationW(hDb, NULL, 0, &hSumInfo); - MsiCloseHandle(hDb); - if (rc == ERROR_SUCCESS) - { - WCHAR guidbuffer[0x200]; - size = 0x200; - rc = MsiSummaryInfoGetPropertyW(hSumInfo, 9, NULL, NULL, NULL, - guidbuffer, &size); - if (rc == ERROR_SUCCESS) - { - /* for now we only care about the first guid */ - LPWSTR ptr = strchrW(guidbuffer,';'); - if (ptr) *ptr = 0; - msi_reg_set_val_str( hukey, INSTALLPROPERTY_PACKAGECODEW, guidbuffer ); - } - else - { - ERR("Unable to query Revision_Number...\n"); - rc = ERROR_SUCCESS; - } - MsiCloseHandle(hSumInfo); - } - else - { - ERR("Unable to open Summary Information\n"); - rc = ERROR_SUCCESS; - } - - /* publish the SourceList info */ - LIST_FOR_EACH_ENTRY(info, &package->sourcelist_info, MSISOURCELISTINFO, entry) - { - if (!lstrcmpW(info->property, INSTALLPROPERTY_LASTUSEDSOURCEW)) - msi_set_last_used_source(package->ProductCode, NULL, info->context, - info->options, info->value); - else - MsiSourceListSetInfoW(package->ProductCode, NULL, - info->context, info->options, - info->property, info->value); - } - - LIST_FOR_EACH_ENTRY(disk, &package->sourcelist_media, MSIMEDIADISK, entry) - { - MsiSourceListAddMediaDiskW(package->ProductCode, NULL, - disk->context, disk->options, - disk->disk_id, disk->volume_label, disk->disk_prompt); - } + rc = msi_publish_icons(package); end: - RegCloseKey(hkey); RegCloseKey(hukey); RegCloseKey(hudkey); - RegCloseKey(props); return rc; } @@ -3876,19 +3947,6 @@ static UINT msi_unpublish_feature(MSIPACKAGE *package, MSIFEATURE *feature) return ERROR_SUCCESS; } -static BOOL msi_check_unpublish(MSIPACKAGE *package) -{ - MSIFEATURE *feature; - - LIST_FOR_EACH_ENTRY(feature, &package->features, MSIFEATURE, entry) - { - if (feature->ActionRequest != INSTALLSTATE_ABSENT) - return FALSE; - } - - return TRUE; -} - static UINT ACTION_UnpublishFeatures(MSIPACKAGE *package) { MSIFEATURE *feature; @@ -4133,6 +4191,7 @@ static UINT ACTION_InstallExecute(MSIPACKAGE *package) static UINT msi_unpublish_product(MSIPACKAGE *package) { + LPWSTR upgrade; LPWSTR remove = NULL; LPWSTR *features = NULL; BOOL full_uninstall = TRUE; @@ -4140,6 +4199,8 @@ static UINT msi_unpublish_product(MSIPACKAGE *package) static const WCHAR szRemove[] = {'R','E','M','O','V','E',0}; static const WCHAR szAll[] = {'A','L','L',0}; + static const WCHAR szUpgradeCode[] = + {'U','p','g','r','a','d','e','C','o','d','e',0}; remove = msi_dup_property(package, szRemove); if (!remove) @@ -4173,6 +4234,13 @@ static UINT msi_unpublish_product(MSIPACKAGE *package) MSIREG_DeleteUserFeaturesKey(package->ProductCode); MSIREG_DeleteUninstallKey(package->ProductCode); + upgrade = msi_dup_property(package, szUpgradeCode); + if (upgrade) + { + MSIREG_DeleteUserUpgradeCodesKey(upgrade); + msi_free(upgrade); + } + done: msi_free(remove); msi_free(features); diff --git a/dlls/msi/files.c b/dlls/msi/files.c index 64869b175ea..08c1959225a 100644 --- a/dlls/msi/files.c +++ b/dlls/msi/files.c @@ -459,6 +459,24 @@ done: return ret; } +/* compares the version of a file read from the filesystem and + * the version specified in the File table + */ +static int msi_compare_file_version(MSIFILE *file) +{ + WCHAR version[MAX_PATH]; + DWORD size; + UINT r; + + size = MAX_PATH; + version[0] = '\0'; + r = MsiGetFileVersionW(file->TargetPath, version, &size, NULL, NULL); + if (r != ERROR_SUCCESS) + return 0; + + return lstrcmpW(version, file->Version); +} + void msi_free_media_info( MSIMEDIAINFO *mi ) { msi_free( mi->disk_prompt ); @@ -544,10 +562,9 @@ UINT msi_load_media_info(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi) options |= MSISOURCETYPE_NETWORK; } - if (mi->type == DRIVE_CDROM || mi->type == DRIVE_REMOVABLE) - msi_package_add_media_disk(package, package->Context, - MSICODE_PRODUCT, mi->disk_id, - mi->volume_label, mi->disk_prompt); + msi_package_add_media_disk(package, package->Context, + MSICODE_PRODUCT, mi->disk_id, + mi->volume_label, mi->disk_prompt); msi_package_add_info(package, package->Context, options, INSTALLPROPERTY_LASTUSEDSOURCEW, source); @@ -803,6 +820,13 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package) continue; } + if (MsiGetFileVersionW(file->TargetPath, NULL, NULL, NULL, NULL) == ERROR_SUCCESS && + msi_compare_file_version(file) >= 0) + { + TRACE("Destination file version greater, not overwriting\n"); + continue; + } + if (file->Sequence > mi->last_sequence || mi->is_continuous || (file->IsCompressed && !mi->is_extracted)) { @@ -973,24 +997,6 @@ UINT ACTION_DuplicateFiles(MSIPACKAGE *package) return rc; } -/* compares the version of a file read from the filesystem and - * the version specified in the File table - */ -static int msi_compare_file_version( MSIFILE *file ) -{ - WCHAR version[MAX_PATH]; - DWORD size; - UINT r; - - size = MAX_PATH; - version[0] = '\0'; - r = MsiGetFileVersionW( file->TargetPath, version, &size, NULL, NULL ); - if ( r != ERROR_SUCCESS ) - return 0; - - return lstrcmpW( version, file->Version ); -} - UINT ACTION_RemoveFiles( MSIPACKAGE *package ) { MSIFILE *file; diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index 1aaf4d93121..f903d058fda 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -1812,6 +1812,7 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) HKEY hkey; INSTALLSTATE r; BOOL missing = FALSE; + BOOL machine = FALSE; TRACE("%s %s\n", debugstr_w(szProduct), debugstr_w(szFeature)); @@ -1821,10 +1822,15 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) if (!squash_guid( szProduct, squishProduct )) return INSTALLSTATE_INVALIDARG; - /* check that it's installed at all */ - rc = MSIREG_OpenUserFeaturesKey(szProduct, &hkey, FALSE); - if (rc != ERROR_SUCCESS) - return INSTALLSTATE_UNKNOWN; + if (MSIREG_OpenManagedFeaturesKey(szProduct, &hkey, FALSE) != ERROR_SUCCESS && + MSIREG_OpenUserFeaturesKey(szProduct, &hkey, FALSE) != ERROR_SUCCESS) + { + rc = MSIREG_OpenLocalClassesFeaturesKey(szProduct, &hkey, FALSE); + if (rc != ERROR_SUCCESS) + return INSTALLSTATE_UNKNOWN; + + machine = TRUE; + } parent_feature = msi_reg_get_val_str( hkey, szFeature ); RegCloseKey(hkey); @@ -1837,8 +1843,11 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) if (r == INSTALLSTATE_ABSENT) return r; - /* now check if it's complete or advertised */ - rc = MSIREG_OpenUserDataFeaturesKey(szProduct, &hkey, FALSE); + if (machine) + rc = MSIREG_OpenLocalUserDataFeaturesKey(szProduct, &hkey, FALSE); + else + rc = MSIREG_OpenUserDataFeaturesKey(szProduct, &hkey, FALSE); + if (rc != ERROR_SUCCESS) return INSTALLSTATE_ADVERTISED; @@ -1862,7 +1871,12 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) } StringFromGUID2(&guid, comp, GUID_SIZE); - rc = MSIREG_OpenUserDataComponentKey(comp, &hkey, FALSE); + + if (machine) + rc = MSIREG_OpenLocalUserDataComponentKey(comp, &hkey, FALSE); + else + rc = MSIREG_OpenUserDataComponentKey(comp, &hkey, FALSE); + if (rc != ERROR_SUCCESS) { msi_free(components); @@ -2281,57 +2295,93 @@ static USERINFOSTATE WINAPI MSI_GetUserInfo(LPCWSTR szProduct, awstring *lpOrgNameBuf, LPDWORD pcchOrgNameBuf, awstring *lpSerialBuf, LPDWORD pcchSerialBuf) { - HKEY hkey; + WCHAR squished_pc[SQUISH_GUID_SIZE]; LPWSTR user, org, serial; - UINT r; USERINFOSTATE state; + HKEY hkey, props; + LPCWSTR orgptr; + UINT r; + + static const WCHAR szEmpty[] = {0}; - TRACE("%s %p %p %p %p %p %p\n",debugstr_w(szProduct), lpUserNameBuf, + TRACE("%s %p %p %p %p %p %p\n", debugstr_w(szProduct), lpUserNameBuf, pcchUserNameBuf, lpOrgNameBuf, pcchOrgNameBuf, lpSerialBuf, pcchSerialBuf); - if (!szProduct) + if (!szProduct || !squash_guid(szProduct, squished_pc)) return USERINFOSTATE_INVALIDARG; - r = MSIREG_OpenUninstallKey(szProduct, &hkey, FALSE); - if (r != ERROR_SUCCESS) + if (MSIREG_OpenLocalManagedProductKey(szProduct, &hkey, FALSE) != ERROR_SUCCESS && + MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE) != ERROR_SUCCESS && + MSIREG_OpenLocalClassesProductKey(szProduct, &hkey, FALSE) != ERROR_SUCCESS) + { return USERINFOSTATE_UNKNOWN; + } - user = msi_reg_get_val_str( hkey, INSTALLPROPERTY_REGOWNERW ); - org = msi_reg_get_val_str( hkey, INSTALLPROPERTY_REGCOMPANYW ); - serial = msi_reg_get_val_str( hkey, INSTALLPROPERTY_PRODUCTIDW ); + if (MSIREG_OpenCurrentUserInstallProps(szProduct, &props, FALSE) != ERROR_SUCCESS && + MSIREG_OpenLocalSystemInstallProps(szProduct, &props, FALSE) != ERROR_SUCCESS) + { + RegCloseKey(hkey); + return USERINFOSTATE_ABSENT; + } + + user = msi_reg_get_val_str(props, INSTALLPROPERTY_REGOWNERW); + org = msi_reg_get_val_str(props, INSTALLPROPERTY_REGCOMPANYW); + serial = msi_reg_get_val_str(props, INSTALLPROPERTY_PRODUCTIDW); + state = USERINFOSTATE_ABSENT; RegCloseKey(hkey); + RegCloseKey(props); - state = USERINFOSTATE_PRESENT; + if (user && serial) + state = USERINFOSTATE_PRESENT; - if (user) + if (pcchUserNameBuf) { - r = msi_strcpy_to_awstring( user, lpUserNameBuf, pcchUserNameBuf ); + if (lpUserNameBuf && !user) + { + (*pcchUserNameBuf)--; + goto done; + } + + r = msi_strcpy_to_awstring(user, lpUserNameBuf, pcchUserNameBuf); if (r == ERROR_MORE_DATA) + { state = USERINFOSTATE_MOREDATA; + goto done; + } } - else - state = USERINFOSTATE_ABSENT; - if (org) + + if (pcchOrgNameBuf) { - r = msi_strcpy_to_awstring( org, lpOrgNameBuf, pcchOrgNameBuf ); - if (r == ERROR_MORE_DATA && state == USERINFOSTATE_PRESENT) + orgptr = org; + if (!orgptr) orgptr = szEmpty; + + r = msi_strcpy_to_awstring(orgptr, lpOrgNameBuf, pcchOrgNameBuf); + if (r == ERROR_MORE_DATA) + { state = USERINFOSTATE_MOREDATA; + goto done; + } } - /* msdn states: The user information is considered to be present even in the absence of a company name. */ - if (serial) + + if (pcchSerialBuf) { - r = msi_strcpy_to_awstring( serial, lpSerialBuf, pcchSerialBuf ); - if (r == ERROR_MORE_DATA && state == USERINFOSTATE_PRESENT) + if (!serial) + { + (*pcchSerialBuf)--; + goto done; + } + + r = msi_strcpy_to_awstring(serial, lpSerialBuf, pcchSerialBuf); + if (r == ERROR_MORE_DATA) state = USERINFOSTATE_MOREDATA; } - else - state = USERINFOSTATE_ABSENT; - msi_free( user ); - msi_free( org ); - msi_free( serial ); +done: + msi_free(user); + msi_free(org); + msi_free(serial); return state; } @@ -2346,6 +2396,11 @@ USERINFOSTATE WINAPI MsiGetUserInfoW(LPCWSTR szProduct, { awstring user, org, serial; + if ((lpUserNameBuf && !pcchUserNameBuf) || + (lpOrgNameBuf && !pcchOrgNameBuf) || + (lpSerialBuf && !pcchSerialBuf)) + return USERINFOSTATE_INVALIDARG; + user.unicode = TRUE; user.str.w = lpUserNameBuf; org.unicode = TRUE; @@ -2367,6 +2422,11 @@ USERINFOSTATE WINAPI MsiGetUserInfoA(LPCSTR szProduct, LPWSTR prod; UINT r; + if ((lpUserNameBuf && !pcchUserNameBuf) || + (lpOrgNameBuf && !pcchOrgNameBuf) || + (lpSerialBuf && !pcchSerialBuf)) + return USERINFOSTATE_INVALIDARG; + prod = strdupAtoW( szProduct ); if (szProduct && !prod) return ERROR_OUTOFMEMORY; diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index b045710ef8a..fe880c621aa 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -773,6 +773,7 @@ extern UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL extern UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create); extern UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY* key, BOOL create); +extern UINT MSIREG_OpenLocalUserDataProductKey(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenCurrentUserInstallProps(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenLocalSystemInstallProps(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create); @@ -787,10 +788,13 @@ extern UINT MSIREG_OpenLocalSystemComponentKey(LPCWSTR szComponent, HKEY *key, B extern UINT MSIREG_OpenLocalClassesProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create); extern UINT MSIREG_OpenLocalClassesFeaturesKey(LPCWSTR szProductCode, HKEY *key, BOOL create); extern UINT MSIREG_OpenLocalManagedProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create); +extern UINT MSIREG_OpenManagedFeaturesKey(LPCWSTR szProductCode, HKEY *key, BOOL create); extern UINT MSIREG_OpenLocalUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create); extern UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct); extern UINT MSIREG_DeleteLocalUserDataComponentKey(LPCWSTR szComponent); extern UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent); +extern UINT MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode); +extern UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create); extern LPWSTR msi_reg_get_val_str( HKEY hkey, LPCWSTR name ); extern BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val); diff --git a/dlls/msi/registry.c b/dlls/msi/registry.c index 7b586a8740b..a12a825f343 100644 --- a/dlls/msi/registry.c +++ b/dlls/msi/registry.c @@ -220,6 +220,21 @@ static const WCHAR szInstaller_LocalManagedProd_fmt[] = { 'I','n','s','t','a','l','l','e','r','\\', 'P','r','o','d','u','c','t','s','\\','%','s',0}; +static const WCHAR szInstaller_LocalManagedFeat_fmt[] = { +'S','o','f','t','w','a','r','e','\\', +'M','i','c','r','o','s','o','f','t','\\', +'W','i','n','d','o','w','s','\\', +'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', +'I','n','s','t','a','l','l','e','r','\\', +'M','a','n','a','g','e','d','\\','%','s','\\', +'I','n','s','t','a','l','l','e','r','\\', +'F','e','a','t','u','r','e','s','\\','%','s',0}; + +static const WCHAR szInstaller_ClassesUpgrade_fmt[] = { +'I','n','s','t','a','l','l','e','r','\\', +'U','p','g','r','a','d','e','C','o','d','e','s','\\', +'%','s',0}; + static const WCHAR localsid[] = {'S','-','1','-','5','-','1','8',0}; BOOL unsquash_guid(LPCWSTR in, LPWSTR out) @@ -809,6 +824,24 @@ UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create) return rc; } +UINT MSIREG_OpenLocalUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n", debugstr_w(szProduct)); + if (!squash_guid(szProduct, squished_pc)) + return ERROR_FUNCTION_FAILED; + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath, szUserDataProd_fmt, localsid, squished_pc); + + if (create) + return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key); + + return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); +} + static UINT MSIREG_OpenInstallProps(LPCWSTR szProduct, LPCWSTR szUserSID, HKEY *key, BOOL create) { @@ -980,6 +1013,21 @@ UINT MSIREG_OpenUserUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL creat return rc; } +UINT MSIREG_DeleteUserUpgradeCodesKey(LPCWSTR szUpgradeCode) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n",debugstr_w(szUpgradeCode)); + if (!squash_guid(szUpgradeCode,squished_pc)) + return ERROR_FUNCTION_FAILED; + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath,szInstaller_UserUpgradeCodes_fmt,squished_pc); + + return RegDeleteTreeW(HKEY_CURRENT_USER, keypath); +} + UINT MSIREG_OpenLocalSystemProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create) { WCHAR squished_pc[GUID_SIZE]; @@ -1090,6 +1138,54 @@ UINT MSIREG_OpenLocalManagedProductKey(LPCWSTR szProductCode, HKEY *key, BOOL cr return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); } +UINT MSIREG_OpenManagedFeaturesKey(LPCWSTR szProductCode, HKEY *key, BOOL create) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + LPWSTR usersid; + UINT r; + + TRACE("%s\n", debugstr_w(szProductCode)); + + if (!squash_guid(szProductCode, squished_pc)) + return ERROR_FUNCTION_FAILED; + + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + r = get_user_sid(&usersid); + if (r != ERROR_SUCCESS || !usersid) + { + ERR("Failed to retrieve user SID: %d\n", r); + return r; + } + + sprintfW(keypath, szInstaller_LocalManagedFeat_fmt, usersid, squished_pc); + LocalFree(usersid); + + if (create) + return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key); + + return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); +} + +UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n", debugstr_w(szUpgradeCode)); + if (!squash_guid(szUpgradeCode, squished_pc)) + return ERROR_FUNCTION_FAILED; + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath, szInstaller_ClassesUpgrade_fmt, squished_pc); + + if (create) + return RegCreateKeyW(HKEY_CLASSES_ROOT, keypath, key); + + return RegOpenKeyW(HKEY_CLASSES_ROOT, keypath, key); +} + /************************************************************************* * MsiDecomposeDescriptorW [MSI.@] * diff --git a/dlls/msi/tests/automation.c b/dlls/msi/tests/automation.c index 2b0ada1ada6..68b0f75c25c 100644 --- a/dlls/msi/tests/automation.c +++ b/dlls/msi/tests/automation.c @@ -2009,9 +2009,12 @@ static void test_Installer_Products(BOOL bProductInstalled) } } - ok(bProductInstalled == bProductFound, "Product expected to %s installed but product code was %s\n", - bProductInstalled ? "be" : "not be", - bProductFound ? "found" : "not found"); + if (bProductInstalled) todo_wine + { + ok(bProductInstalled == bProductFound, "Product expected to %s installed but product code was %s\n", + bProductInstalled ? "be" : "not be", + bProductFound ? "found" : "not found"); + } if (pEnum) { @@ -2298,15 +2301,12 @@ static void test_Installer_InstallProduct(void) ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); res = RegDeleteKeyA(hkey, "UpgradeCodes\\D8E760ECA1E276347B43E42BDBDA5656"); - todo_wine - { - ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - } + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); RegCloseKey(hkey); res = RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\Products\\05FA3C1F65B896A40AC00077F34EF203"); - todo_wine ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_SUCCESS, got %d\n", res); + ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); /* Delete installation files we installed */ delete_test_files(); diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 93445c961cb..8fa729a0833 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -2154,7 +2154,8 @@ static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase val[0] = '\0'; res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size); - if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ)) + if (res != ERROR_SUCCESS || + (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_MULTI_SZ)) { ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n"); return; @@ -2464,7 +2465,7 @@ static void test_publish_publishproduct(void) UINT r; LONG res; LPSTR usersid; - HKEY sourcelist, net; + HKEY sourcelist, net, props; HKEY hkey, patches, media; CHAR keypath[MAX_PATH]; CHAR temp[MAX_PATH]; @@ -2477,6 +2478,11 @@ static void test_publish_publishproduct(void) "\\84A88FD7F6998CE40A22FB59F6B9C2BB"; static const CHAR cuupgrades[] = "Software\\Microsoft\\Installer\\UpgradeCodes" "\\51AAE0C44620A5E4788506E91F249BD2"; + static const CHAR badprod[] = "Software\\Microsoft\\Windows\\CurrentVersion" + "\\Installer\\Products" + "\\84A88FD7F6998CE40A22FB59F6B9C2BB"; + static const CHAR machprod[] = "Installer\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB"; + static const CHAR machup[] = "Installer\\UpgradeCodes\\51AAE0C44620A5E4788506E91F249BD2"; get_user_sid(&usersid); if (!usersid) @@ -2500,10 +2506,16 @@ static void test_publish_publishproduct(void) ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n"); ok(delete_pf("msitest", FALSE), "File not installed\n"); + res = RegOpenKeyA(HKEY_LOCAL_MACHINE, badprod, &hkey); + ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); + sprintf(keypath, prodpath, usersid); res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + res = RegOpenKeyA(hkey, "InstallProperties", &props); + ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); + res = RegOpenKeyA(hkey, "Patches", &patches); todo_wine { @@ -2521,17 +2533,14 @@ static void test_publish_publishproduct(void) ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); CHECK_DEL_REG_STR(hkey, "ProductName", "MSITEST"); + CHECK_DEL_REG_STR(hkey, "PackageCode", "AC75740029052c94DA02821EECD05F2F"); CHECK_DEL_REG_DWORD(hkey, "Language", 1033); CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001); CHECK_DEL_REG_DWORD(hkey, "AuthorizedLUAApp", 0); - todo_wine - { - CHECK_DEL_REG_STR(hkey, "PackageCode", "AC75740029052c94DA02821EECD05F2F"); - CHECK_DEL_REG_DWORD(hkey, "Assignment", 0); - CHECK_DEL_REG_DWORD(hkey, "AdvertiseFlags", 0x184); - CHECK_DEL_REG_DWORD(hkey, "InstanceType", 0); - CHECK_DEL_REG_STR(hkey, "Clients", ":"); - } + CHECK_DEL_REG_DWORD(hkey, "Assignment", 0); + CHECK_DEL_REG_DWORD(hkey, "AdvertiseFlags", 0x184); + CHECK_DEL_REG_DWORD(hkey, "InstanceType", 0); + CHECK_DEL_REG_STR(hkey, "Clients", ":"); res = RegOpenKeyA(hkey, "SourceList", &sourcelist); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); @@ -2552,10 +2561,7 @@ static void test_publish_publishproduct(void) res = RegOpenKeyA(sourcelist, "Media", &media); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - todo_wine - { - CHECK_DEL_REG_STR(media, "1", "DISK1;"); - } + CHECK_DEL_REG_STR(media, "1", "DISK1;"); RegDeleteKeyA(media, ""); RegCloseKey(media); @@ -2565,13 +2571,88 @@ static void test_publish_publishproduct(void) RegCloseKey(hkey); res = RegOpenKeyA(HKEY_CURRENT_USER, cuupgrades, &hkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL); + + RegDeleteKeyA(hkey, ""); + RegCloseKey(hkey); + + /* PublishProduct, machine */ + r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1 ALLUSERS=1"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n"); + ok(delete_pf("msitest", FALSE), "File not installed\n"); + + res = RegOpenKeyA(HKEY_LOCAL_MACHINE, badprod, &hkey); + ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); + + sprintf(keypath, prodpath, "S-1-5-18"); + res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegOpenKeyA(hkey, "InstallProperties", &props); + ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); + + res = RegOpenKeyA(hkey, "Patches", &patches); todo_wine { ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); - CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL); + CHECK_DEL_REG_STR(patches, "AllPatches", NULL); } + RegDeleteKeyA(patches, ""); + RegCloseKey(patches); + RegDeleteKeyA(hkey, ""); + RegCloseKey(hkey); + + res = RegOpenKeyA(HKEY_CLASSES_ROOT, machprod, &hkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + CHECK_DEL_REG_STR(hkey, "ProductName", "MSITEST"); + CHECK_DEL_REG_STR(hkey, "PackageCode", "AC75740029052c94DA02821EECD05F2F"); + CHECK_DEL_REG_DWORD(hkey, "Language", 1033); + CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001); + CHECK_DEL_REG_DWORD(hkey, "AuthorizedLUAApp", 0); + todo_wine CHECK_DEL_REG_DWORD(hkey, "Assignment", 1); + CHECK_DEL_REG_DWORD(hkey, "AdvertiseFlags", 0x184); + CHECK_DEL_REG_DWORD(hkey, "InstanceType", 0); + CHECK_DEL_REG_STR(hkey, "Clients", ":"); + + res = RegOpenKeyA(hkey, "SourceList", &sourcelist); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + lstrcpyA(path, "n;1;"); + lstrcatA(path, temp); + CHECK_DEL_REG_STR(sourcelist, "LastUsedSource", path); + CHECK_DEL_REG_STR(sourcelist, "PackageName", "msitest.msi"); + + res = RegOpenKeyA(sourcelist, "Net", &net); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + CHECK_DEL_REG_STR(net, "1", temp); + + RegDeleteKeyA(net, ""); + RegCloseKey(net); + + res = RegOpenKeyA(sourcelist, "Media", &media); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + CHECK_DEL_REG_STR(media, "1", "DISK1;"); + + RegDeleteKeyA(media, ""); + RegCloseKey(media); + RegDeleteKeyA(sourcelist, ""); + RegCloseKey(sourcelist); + RegDeleteKeyA(hkey, ""); + RegCloseKey(hkey); + + res = RegOpenKeyA(HKEY_CLASSES_ROOT, machup, &hkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL); + RegDeleteKeyA(hkey, ""); RegCloseKey(hkey); diff --git a/dlls/msi/tests/msi.c b/dlls/msi/tests/msi.c index b704d2b13b8..52cfd74564e 100644 --- a/dlls/msi/tests/msi.c +++ b/dlls/msi/tests/msi.c @@ -735,6 +735,8 @@ static void test_MsiQueryFeatureState(void) state = MsiQueryFeatureStateA(prodcode, "feature"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); + /* MSIINSTALLCONTEXT_USERUNMANAGED */ + lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Features\\"); lstrcatA(keypath, prod_squashed); @@ -748,6 +750,7 @@ static void test_MsiQueryFeatureState(void) res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + /* feature value exists */ state = MsiQueryFeatureStateA(prodcode, "feature"); ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); @@ -760,6 +763,7 @@ static void test_MsiQueryFeatureState(void) res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + /* userdata features key exists */ state = MsiQueryFeatureStateA(prodcode, "feature"); ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); @@ -811,7 +815,183 @@ static void test_MsiQueryFeatureState(void) ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); RegDeleteValueA(compkey, prod_squashed); - RegDeleteValueA(compkey, ""); + RegDeleteKeyA(compkey, ""); + RegDeleteValueA(localkey, "feature"); + RegDeleteValueA(userkey, "feature"); + RegDeleteKeyA(userkey, ""); + RegCloseKey(compkey); + RegCloseKey(localkey); + RegCloseKey(userkey); + + /* MSIINSTALLCONTEXT_USERMANAGED */ + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\"); + lstrcatA(keypath, usersid); + lstrcatA(keypath, "\\Installer\\Features\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* feature key exists */ + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); + + res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* feature value exists */ + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"); + lstrcatA(keypath, usersid); + lstrcatA(keypath, "\\Products\\"); + lstrcatA(keypath, prod_squashed); + lstrcatA(keypath, "\\Features"); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* userdata features key exists */ + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state); + + res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 21); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"); + lstrcatA(keypath, usersid); + lstrcatA(keypath, "\\Components\\"); + lstrcatA(keypath, comp_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); + + res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 1); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); + + RegDeleteValueA(compkey, prod_squashed); + RegDeleteKeyA(compkey, ""); + RegDeleteValueA(localkey, "feature"); + RegDeleteValueA(userkey, "feature"); + RegDeleteKeyA(userkey, ""); + RegCloseKey(compkey); + RegCloseKey(localkey); + RegCloseKey(userkey); + + /* MSIINSTALLCONTEXT_MACHINE */ + + lstrcpyA(keypath, "Software\\Classes\\Installer\\Features\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* feature key exists */ + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); + + res = RegSetValueExA(userkey, "feature", 0, REG_SZ, (const BYTE *)"", 2); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* feature value exists */ + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"); + lstrcatA(keypath, "S-1-5-18\\Products\\"); + lstrcatA(keypath, prod_squashed); + lstrcatA(keypath, "\\Features"); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* userdata features key exists */ + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state); + + res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 21); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"); + lstrcatA(keypath, "S-1-5-18\\Components\\"); + lstrcatA(keypath, comp_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &compkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); + + res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 1); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryFeatureStateA(prodcode, "feature"); + ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); + + RegDeleteValueA(compkey, prod_squashed); + RegDeleteKeyA(compkey, ""); RegDeleteValueA(localkey, "feature"); RegDeleteValueA(userkey, "feature"); RegDeleteKeyA(userkey, ""); @@ -2110,6 +2290,10 @@ static void test_MsiGetFileVersion(void) ok(!lstrcmpA(lang, langcheck), "Expected %s, got %s\n", langcheck, lang); ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz); + /* check neither version nor language */ + r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + /* get pcchVersionBuf */ versz = MAX_PATH; r = MsiGetFileVersionA(path, NULL, &versz, NULL, NULL); @@ -6138,6 +6322,585 @@ static void test_MsiGetProductInfoEx(void) RegCloseKey(prodkey); } +#define INIT_USERINFO() \ + lstrcpyA(user, "apple"); \ + lstrcpyA(org, "orange"); \ + lstrcpyA(serial, "banana"); \ + usersz = orgsz = serialsz = MAX_PATH; + +static void test_MsiGetUserInfo(void) +{ + USERINFOSTATE state; + CHAR user[MAX_PATH]; + CHAR org[MAX_PATH]; + CHAR serial[MAX_PATH]; + DWORD usersz, orgsz, serialsz; + CHAR keypath[MAX_PATH * 2]; + CHAR prodcode[MAX_PATH]; + CHAR prod_squashed[MAX_PATH]; + HKEY prodkey, userprod, props; + LPSTR usersid; + LONG res; + + create_test_guid(prodcode, prod_squashed); + get_user_sid(&usersid); + + /* NULL szProduct */ + INIT_USERINFO(); + state = MsiGetUserInfoA(NULL, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_INVALIDARG, + "Expected USERINFOSTATE_INVALIDARG, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* empty szProductCode */ + INIT_USERINFO(); + state = MsiGetUserInfoA("", user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_INVALIDARG, + "Expected USERINFOSTATE_INVALIDARG, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* garbage szProductCode */ + INIT_USERINFO(); + state = MsiGetUserInfoA("garbage", user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_INVALIDARG, + "Expected USERINFOSTATE_INVALIDARG, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* guid without brackets */ + INIT_USERINFO(); + state = MsiGetUserInfoA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", + user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_INVALIDARG, + "Expected USERINFOSTATE_INVALIDARG, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* guid with brackets */ + INIT_USERINFO(); + state = MsiGetUserInfoA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", + user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_UNKNOWN, + "Expected USERINFOSTATE_UNKNOWN, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* NULL lpUserNameBuf */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_UNKNOWN, + "Expected USERINFOSTATE_UNKNOWN, got %d\n", state); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* NULL pcchUserNameBuf */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, NULL, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_INVALIDARG, + "Expected USERINFOSTATE_INVALIDARG, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* both lpUserNameBuf and pcchUserNameBuf NULL */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_UNKNOWN, + "Expected USERINFOSTATE_UNKNOWN, got %d\n", state); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* NULL lpOrgNameBuf */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_UNKNOWN, + "Expected USERINFOSTATE_UNKNOWN, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* NULL pcchOrgNameBuf */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, NULL, serial, &serialsz); + ok(state == USERINFOSTATE_INVALIDARG, + "Expected USERINFOSTATE_INVALIDARG, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* both lpOrgNameBuf and pcchOrgNameBuf NULL */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, NULL, NULL, serial, &serialsz); + ok(state == USERINFOSTATE_UNKNOWN, + "Expected USERINFOSTATE_UNKNOWN, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* NULL lpSerialBuf */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, &serialsz); + ok(state == USERINFOSTATE_UNKNOWN, + "Expected USERINFOSTATE_UNKNOWN, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* NULL pcchSerialBuf */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, NULL); + ok(state == USERINFOSTATE_INVALIDARG, + "Expected USERINFOSTATE_INVALIDARG, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + + /* both lpSerialBuf and pcchSerialBuf NULL */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, NULL, NULL); + ok(state == USERINFOSTATE_UNKNOWN, + "Expected USERINFOSTATE_UNKNOWN, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + + /* MSIINSTALLCONTEXT_USERMANAGED */ + + /* create local system product key */ + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\"); + lstrcatA(keypath, usersid); + lstrcatA(keypath, "\\Installer\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* managed product key exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\"); + lstrcatA(keypath, "Installer\\UserData\\"); + lstrcatA(keypath, usersid); + lstrcatA(keypath, "\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userprod); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegCreateKeyA(userprod, "InstallProperties", &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* InstallProperties key exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(orgsz == 0, "Expected 0, got %d\n", orgsz); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + /* RegOwner, RegCompany don't exist, out params are NULL */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* RegOwner value exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user); + ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == 0, "Expected 0, got %d\n", orgsz); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* RegCompany value exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user); + ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == 7, "Expected 7, got %d\n", orgsz); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* ProductID value exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_PRESENT, + "Expected USERINFOSTATE_PRESENT, got %d\n", state); + ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user); + ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org); + ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == 7, "Expected 7, got %d\n", orgsz); + ok(serialsz == 2, "Expected 2, got %d\n", serialsz); + + /* pcchUserNameBuf is too small */ + INIT_USERINFO(); + usersz = 0; + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_MOREDATA, + "Expected USERINFOSTATE_MOREDATA, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* pcchUserNameBuf has no room for NULL terminator */ + INIT_USERINFO(); + usersz = 5; + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_MOREDATA, + "Expected USERINFOSTATE_MOREDATA, got %d\n", state); + todo_wine + { + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + } + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* pcchUserNameBuf is too small, lpUserNameBuf is NULL */ + INIT_USERINFO(); + usersz = 0; + state = MsiGetUserInfoA(prodcode, NULL, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_PRESENT, + "Expected USERINFOSTATE_PRESENT, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org); + ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == 7, "Expected 7, got %d\n", orgsz); + ok(serialsz == 2, "Expected 2, got %d\n", serialsz); + + RegDeleteValueA(props, "ProductID"); + RegDeleteValueA(props, "RegCompany"); + RegDeleteValueA(props, "RegOwner"); + RegDeleteKeyA(props, ""); + RegCloseKey(props); + RegDeleteKeyA(userprod, ""); + RegCloseKey(userprod); + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); + + /* MSIINSTALLCONTEXT_USERUNMANAGED */ + + /* create local system product key */ + lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* product key exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\"); + lstrcatA(keypath, "Installer\\UserData\\"); + lstrcatA(keypath, usersid); + lstrcatA(keypath, "\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userprod); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegCreateKeyA(userprod, "InstallProperties", &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* InstallProperties key exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(orgsz == 0, "Expected 0, got %d\n", orgsz); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + /* RegOwner, RegCompany don't exist, out params are NULL */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* RegOwner value exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user); + ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == 0, "Expected 0, got %d\n", orgsz); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* RegCompany value exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user); + ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == 7, "Expected 7, got %d\n", orgsz); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* ProductID value exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_PRESENT, + "Expected USERINFOSTATE_PRESENT, got %d\n", state); + ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user); + ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org); + ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == 7, "Expected 7, got %d\n", orgsz); + ok(serialsz == 2, "Expected 2, got %d\n", serialsz); + + RegDeleteValueA(props, "ProductID"); + RegDeleteValueA(props, "RegCompany"); + RegDeleteValueA(props, "RegOwner"); + RegDeleteKeyA(props, ""); + RegCloseKey(props); + RegDeleteKeyA(userprod, ""); + RegCloseKey(userprod); + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); + + /* MSIINSTALLCONTEXT_MACHINE */ + + /* create local system product key */ + lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* product key exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH, "Expected MAX_PATH, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\"); + lstrcatA(keypath, "Installer\\UserData\\S-1-5-18"); + lstrcatA(keypath, "\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userprod); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + res = RegCreateKeyA(userprod, "InstallProperties", &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* InstallProperties key exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "apple"), "Expected user to be unchanged, got \"%s\"\n", user); + ok(!lstrcmpA(org, "orange"), "Expected org to be unchanged, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", usersz); + ok(orgsz == MAX_PATH, "Expected MAX_PATH, got %d\n", orgsz); + ok(serialsz == MAX_PATH, "Expected MAX_PATH, got %d\n", serialsz); + + /* RegOwner doesn't exist, lpUserNameBuf and pcchUserNameBuf are NULL */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, NULL, NULL, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(orgsz == 0, "Expected 0, got %d\n", orgsz); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + /* RegOwner, RegCompany don't exist, out params are NULL */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, NULL, NULL, NULL, NULL, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + res = RegSetValueExA(props, "RegOwner", 0, REG_SZ, (LPBYTE)"owner", 6); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* RegOwner value exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user); + ok(!lstrcmpA(org, ""), "Expected empty string, got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == 0, "Expected 0, got %d\n", orgsz); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + res = RegSetValueExA(props, "RegCompany", 0, REG_SZ, (LPBYTE)"company", 8); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* RegCompany value exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_ABSENT, + "Expected USERINFOSTATE_ABSENT, got %d\n", state); + ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user); + ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org); + ok(!lstrcmpA(serial, "banana"), "Expected serial to be unchanged, got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == 7, "Expected 7, got %d\n", orgsz); + ok(serialsz == MAX_PATH - 1, "Expected MAX_PATH - 1, got %d\n", serialsz); + + res = RegSetValueExA(props, "ProductID", 0, REG_SZ, (LPBYTE)"ID", 3); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* ProductID value exists */ + INIT_USERINFO(); + state = MsiGetUserInfoA(prodcode, user, &usersz, org, &orgsz, serial, &serialsz); + ok(state == USERINFOSTATE_PRESENT, + "Expected USERINFOSTATE_PRESENT, got %d\n", state); + ok(!lstrcmpA(user, "owner"), "Expected \"owner\", got \"%s\"\n", user); + ok(!lstrcmpA(org, "company"), "Expected \"company\", got \"%s\"\n", org); + ok(!lstrcmpA(serial, "ID"), "Expected \"ID\", got \"%s\"\n", serial); + ok(usersz == 5, "Expected 5, got %d\n", usersz); + ok(orgsz == 7, "Expected 7, got %d\n", orgsz); + ok(serialsz == 2, "Expected 2, got %d\n", serialsz); + + RegDeleteValueA(props, "ProductID"); + RegDeleteValueA(props, "RegCompany"); + RegDeleteValueA(props, "RegOwner"); + RegDeleteKeyA(props, ""); + RegCloseKey(props); + RegDeleteKeyA(userprod, ""); + RegCloseKey(userprod); + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); +} + START_TEST(msi) { init_functionpointers(); @@ -6160,6 +6923,7 @@ START_TEST(msi) test_MsiEnumClients(); test_MsiGetProductInfo(); test_MsiGetProductInfoEx(); + test_MsiGetUserInfo(); } test_MsiGetFileVersion(); diff --git a/dlls/msxml3/factory.c b/dlls/msxml3/factory.c index cd0d1088b9f..beb5bbcf8b2 100644 --- a/dlls/msxml3/factory.c +++ b/dlls/msxml3/factory.c @@ -159,7 +159,8 @@ HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID iid, LPVOID *ppv ) { cf = (IClassFactory*) &xmldoccf.lpVtbl; } - else if( IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument ) ) + else if( IsEqualCLSID( rclsid, &CLSID_DOMFreeThreadedDocument ) || /* Version indep. v 2.x */ + IsEqualCLSID( rclsid, &CLSID_FreeThreadedDOMDocument ) ) { cf = (IClassFactory*) &domdoccf.lpVtbl; } diff --git a/dlls/msxml3/tests/xmlelem.c b/dlls/msxml3/tests/xmlelem.c index 71d9027efae..ab83329cac5 100644 --- a/dlls/msxml3/tests/xmlelem.c +++ b/dlls/msxml3/tests/xmlelem.c @@ -80,7 +80,7 @@ static void test_xmlelem(void) hr = IXMLElement_getAttribute(element, str, &vValue); ok(hr == S_FALSE, "Expected S_FALSE, got %d\n", hr); ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue)); - ok(lstrlenW(V_BSTR(&vValue)) == 0, "Expected empty value\n"); + ok(V_BSTR(&vValue) == NULL, "Expected null value\n"); VariantClear(&vValue); SysFreeString(str); @@ -125,7 +125,7 @@ static void test_xmlelem(void) hr = IXMLElement_getAttribute(element, str, &vValue); ok(hr == 1, "Expected 1, got %d\n", hr); ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue)); - ok(!lstrlenW(V_BSTR(&vValue)), "Expected empty value\n"); + ok(V_BSTR(&vValue) == NULL, "Expected null value\n"); SysFreeString(str); VariantClear(&vValue); diff --git a/dlls/netapi32/tests/access.c b/dlls/netapi32/tests/access.c index eae713f6e3b..1e1dbf20e6e 100644 --- a/dlls/netapi32/tests/access.c +++ b/dlls/netapi32/tests/access.c @@ -51,7 +51,6 @@ static WCHAR sTooLongPassword[] = {'a','b','c','d','e','f','g','h','a','b','c',' static WCHAR sTestUserName[] = {'t', 'e', 's', 't', 'u', 's', 'e', 'r', 0}; static WCHAR sTestUserOldPass[] = {'O', 'l', 'd', 'P', 'a', 's', 's', 'W', '0', 'r', 'd', 'S', 'e', 't', '!', '~', 0}; -static WCHAR sTestUserNewPass[] = {'N', 'e', 'w', 'P', 'a', 's', 's', 'W', '0', 'r', 'd', 'S', 'e', 't', '!', '~', 0}; static const WCHAR sBadNetPath[] = {'\\','\\','B','a',' ',' ','p','a','t','h',0}; static const WCHAR sInvalidName[] = {'\\',0}; static const WCHAR sInvalidName2[] = {'\\','\\',0}; @@ -63,7 +62,6 @@ static NET_API_STATUS (WINAPI *pNetQueryDisplayInformation)(LPWSTR,DWORD,DWORD,D static NET_API_STATUS (WINAPI *pNetUserGetInfo)(LPCWSTR,LPCWSTR,DWORD,LPBYTE*)=NULL; static NET_API_STATUS (WINAPI *pNetUserModalsGet)(LPCWSTR,DWORD,LPBYTE*)=NULL; static NET_API_STATUS (WINAPI *pNetUserAdd)(LPCWSTR,DWORD,LPBYTE,LPDWORD)=NULL; -static NET_API_STATUS (WINAPI *pNetUserChangePassword)(LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR)=NULL; static NET_API_STATUS (WINAPI *pNetUserDel)(LPCWSTR,LPCWSTR)=NULL; static int init_access_tests(void) @@ -294,35 +292,13 @@ static void run_userhandling_tests(void) if(ret != NERR_Success) return; - ret = pNetUserChangePassword(NULL, sNonexistentUser, sTestUserOldPass, - sTestUserNewPass); - ok(ret == NERR_UserNotFound || ret == ERROR_INVALID_PASSWORD || - ret == ERROR_CANT_ACCESS_DOMAIN_INFO, - "Changing password for nonexistent user returned 0x%08x.\n", ret); - - ret = pNetUserChangePassword(NULL, sTestUserName, sTestUserOldPass, - sTestUserOldPass); - /* Apparently NERR_PasswordTooShort can be returned on windows xp if a - * strict password policy is enforced + /* On Windows XP (and newer), calling NetUserChangePassword with a NULL + * domainname parameter creates a user home directory, iff the machine is + * not member of a domain. + * Using \\127.0.0.1 as domain name does not work on standalone machines + * either, unless the ForceGuest option in the registry is turned off. + * So let's not test NetUserChangePassword for now. */ - ok(ret == NERR_Success || ret == NERR_PasswordTooShort || - ret == ERROR_CANT_ACCESS_DOMAIN_INFO || ret == ERROR_INVALID_PASSWORD, - "Changing old password to old password returned 0x%08x.\n", ret); - - ret = pNetUserChangePassword(NULL, sTestUserName, sTestUserNewPass, - sTestUserOldPass); - ok(ret == ERROR_INVALID_PASSWORD || ret == ERROR_CANT_ACCESS_DOMAIN_INFO, - "Trying to change password giving an invalid password returned 0x%08x.\n", ret); - - ret = pNetUserChangePassword(NULL, sTestUserName, sTestUserOldPass, - sTooLongPassword); - ok(ret == ERROR_PASSWORD_RESTRICTION, - "Changing to a password that's too long returned 0x%08x.\n", ret); - - ret = pNetUserChangePassword(NULL, sTestUserName, sTestUserOldPass, - sTestUserNewPass); - ok(ret == NERR_Success || ret == ERROR_CANT_ACCESS_DOMAIN_INFO || - ret == ERROR_INVALID_PASSWORD, "Changing the password correctly returned 0x%08x.\n", ret); ret = pNetUserDel(NULL, sTestUserName); ok(ret == NERR_Success, "Deleting the user failed.\n"); @@ -341,7 +317,6 @@ START_TEST(access) pNetUserGetInfo=(void*)GetProcAddress(hnetapi32,"NetUserGetInfo"); pNetUserModalsGet=(void*)GetProcAddress(hnetapi32,"NetUserModalsGet"); pNetUserAdd=(void*)GetProcAddress(hnetapi32, "NetUserAdd"); - pNetUserChangePassword=(void*)GetProcAddress(hnetapi32, "NetUserChangePassword"); pNetUserDel=(void*)GetProcAddress(hnetapi32, "NetUserDel"); /* These functions were introduced with NT. It's safe to assume that diff --git a/dlls/netapi32/tests/apibuf.c b/dlls/netapi32/tests/apibuf.c index 920be6ae05e..5589c1819d6 100644 --- a/dlls/netapi32/tests/apibuf.c +++ b/dlls/netapi32/tests/apibuf.c @@ -54,9 +54,6 @@ static void run_apibuf_tests(void) ok(pNetApiBufferFree(p) == NERR_Success, "Freed\n"); - /* test errors handling */ - ok(pNetApiBufferFree(p) == NERR_Success, "Freed\n"); - ok(pNetApiBufferSize(p, &dwSize) == NERR_Success, "Got size\n"); ok(pNetApiBufferSize(NULL, &dwSize) == ERROR_INVALID_PARAMETER, "Error for NULL pointer\n"); diff --git a/dlls/ntdll/critsection.c b/dlls/ntdll/critsection.c index 0fa47c49bce..284634353b4 100644 --- a/dlls/ntdll/critsection.c +++ b/dlls/ntdll/critsection.c @@ -247,13 +247,14 @@ static inline NTSTATUS wait_semaphore( RTL_CRITICAL_SECTION *crit, int timeout ) * STATUS_SUCCESS. * * SEE + * RtlInitializeCriticalSectionEx(), * RtlInitializeCriticalSectionAndSpinCount(), RtlDeleteCriticalSection(), * RtlEnterCriticalSection(), RtlLeaveCriticalSection(), * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount() */ NTSTATUS WINAPI RtlInitializeCriticalSection( RTL_CRITICAL_SECTION *crit ) { - return RtlInitializeCriticalSectionAndSpinCount( crit, 0 ); + return RtlInitializeCriticalSectionEx( crit, 0, 0 ); } /*********************************************************************** @@ -272,13 +273,53 @@ NTSTATUS WINAPI RtlInitializeCriticalSection( RTL_CRITICAL_SECTION *crit ) * Available on NT4 SP3 or later. * * SEE + * RtlInitializeCriticalSectionEx(), * RtlInitializeCriticalSection(), RtlDeleteCriticalSection(), * RtlEnterCriticalSection(), RtlLeaveCriticalSection(), * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount() */ NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount( RTL_CRITICAL_SECTION *crit, ULONG spincount ) { - crit->DebugInfo = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_CRITICAL_SECTION_DEBUG)); + return RtlInitializeCriticalSectionEx( crit, spincount, 0 ); +} + +/*********************************************************************** + * RtlInitializeCriticalSectionEx (NTDLL.@) + * + * Initialises a new critical section with a given spin count and flags. + * + * PARAMS + * crit [O] Critical section to initialise. + * spincount [I] Number of times to spin upon contention. + * flags [I] RTL_CRITICAL_SECTION_FLAG_ flags from winnt.h. + * + * RETURNS + * STATUS_SUCCESS. + * + * NOTES + * Available on Vista or later. + * + * SEE + * RtlInitializeCriticalSection(), RtlDeleteCriticalSection(), + * RtlEnterCriticalSection(), RtlLeaveCriticalSection(), + * RtlTryEnterCriticalSection(), RtlSetCriticalSectionSpinCount() + */ +NTSTATUS WINAPI RtlInitializeCriticalSectionEx( RTL_CRITICAL_SECTION *crit, ULONG spincount, ULONG flags ) +{ + if (flags & (RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN|RTL_CRITICAL_SECTION_FLAG_STATIC_INIT)) + FIXME("(%p,%u,0x%08x) semi-stub\n", crit, spincount, flags); + + /* FIXME: if RTL_CRITICAL_SECTION_FLAG_STATIC_INIT is given, we should use + * memory from a static pool to hold the debug info. Then heap.c could pass + * this flag rather than initialising the process heap CS by hand. If this + * is done, then debug info should be managed through Rtlp[Allocate|Free]DebugInfo + * so (e.g.) MakeCriticalSectionGlobal() doesn't free it using HeapFree(). + */ + if (flags & RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO) + crit->DebugInfo = NULL; + else + crit->DebugInfo = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_CRITICAL_SECTION_DEBUG)); + if (crit->DebugInfo) { crit->DebugInfo->Type = 0; @@ -315,6 +356,7 @@ NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount( RTL_CRITICAL_SECTION * * If the system is not SMP, spincount is ignored and set to 0. * * SEE + * RtlInitializeCriticalSectionEx(), * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() @@ -339,6 +381,7 @@ ULONG WINAPI RtlSetCriticalSectionSpinCount( RTL_CRITICAL_SECTION *crit, ULONG s * STATUS_SUCCESS. * * SEE + * RtlInitializeCriticalSectionEx(), * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() @@ -380,6 +423,7 @@ NTSTATUS WINAPI RtlDeleteCriticalSection( RTL_CRITICAL_SECTION *crit ) * faster. * * SEE + * RtlInitializeCriticalSectionEx(), * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() @@ -442,6 +486,7 @@ NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit ) * faster. * * SEE + * RtlInitializeCriticalSectionEx(), * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() @@ -473,6 +518,7 @@ NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) * STATUS_SUCCESS. The critical section is held by the caller. * * SEE + * RtlInitializeCriticalSectionEx(), * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), * RtlDeleteCriticalSection(), RtlSetCriticalSectionSpinCount(), * RtlLeaveCriticalSection(), RtlTryEnterCriticalSection() @@ -526,6 +572,7 @@ done: * Failure: FALSE. The critical section is currently held by another thread. * * SEE + * RtlInitializeCriticalSectionEx(), * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), * RtlLeaveCriticalSection(), RtlSetCriticalSectionSpinCount() @@ -561,6 +608,7 @@ BOOL WINAPI RtlTryEnterCriticalSection( RTL_CRITICAL_SECTION *crit ) * STATUS_SUCCESS. * * SEE + * RtlInitializeCriticalSectionEx(), * RtlInitializeCriticalSection(), RtlInitializeCriticalSectionAndSpinCount(), * RtlDeleteCriticalSection(), RtlEnterCriticalSection(), * RtlSetCriticalSectionSpinCount(), RtlTryEnterCriticalSection() diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index c05e01fcf22..5d47b19d140 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2423,11 +2423,7 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3, status = wine_call_on_stack( attach_process_dlls, wm, NtCurrentTeb()->Tib.StackBase ); if (status != STATUS_SUCCESS) goto error; - /* clear the stack contents before calling the main entry point, some broken apps need that */ - wine_anon_mmap( NtCurrentTeb()->Tib.StackLimit, - (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit, - PROT_READ | PROT_WRITE, MAP_FIXED ); - + virtual_clear_thread_stack(); if (nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) VIRTUAL_UseLargeAddressSpace(); return; diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index ed89cbd4b36..575f99da373 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -664,6 +664,7 @@ @ stub RtlInitializeContext @ stdcall RtlInitializeCriticalSection(ptr) @ stdcall RtlInitializeCriticalSectionAndSpinCount(ptr long) +@ stdcall RtlInitializeCriticalSectionEx(ptr long long) @ stdcall RtlInitializeGenericTable(ptr ptr ptr ptr ptr) # @ stub RtlInitializeGenericTableAvl @ stdcall RtlInitializeHandleTable(long long ptr) diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index cba9643fd62..6f428e0a2aa 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -134,6 +134,7 @@ extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] /* virtual memory */ extern NTSTATUS virtual_alloc_thread_stack( void *base, SIZE_T stack_size ); +extern void virtual_clear_thread_stack(void); extern BOOL virtual_handle_stack_fault( void *addr ); extern NTSTATUS VIRTUAL_HandleFault(LPCVOID addr); extern void VIRTUAL_SetForceExec( BOOL enable ); diff --git a/dlls/ntdll/tests/rtlstr.c b/dlls/ntdll/tests/rtlstr.c index aa4a3911203..74ba8ea7a96 100644 --- a/dlls/ntdll/tests/rtlstr.c +++ b/dlls/ntdll/tests/rtlstr.c @@ -1678,7 +1678,11 @@ static void test_RtlIsTextUnicode(void) { char ascii[] = "A simple string"; WCHAR unicode[] = {'A',' ','U','n','i','c','o','d','e',' ','s','t','r','i','n','g',0}; + WCHAR unicode_no_controls[] = {'A','U','n','i','c','o','d','e','s','t','r','i','n','g',0}; + /* String with both byte-reversed and standard Unicode control characters. */ + WCHAR mixed_controls[] = {'\t',0x9000,0x0d00,'\n',0}; WCHAR *be_unicode; + WCHAR *be_unicode_no_controls; int flags; int i; @@ -1721,7 +1725,81 @@ static void test_RtlIsTextUnicode(void) todo_wine ok(flags == (IS_TEXT_UNICODE_REVERSE_CONTROLS | IS_TEXT_UNICODE_REVERSE_SIGNATURE), "Expected flags 0xc0, obtained %x\n", flags); + + /* build byte reversed unicode string with no control chars */ + be_unicode_no_controls = HeapAlloc(GetProcessHeap(), 0, sizeof(unicode) + sizeof(WCHAR)); + ok(be_unicode_no_controls != NULL, "Expeced HeapAlloc to succeed.\n"); + be_unicode_no_controls[0] = 0xfffe; + for (i = 0; i < sizeof(unicode_no_controls)/sizeof(unicode_no_controls[0]); i++) + be_unicode_no_controls[i + 1] = (unicode_no_controls[i] >> 8) | ((unicode_no_controls[i] & 0xff) << 8); + + + /* The following tests verify that the tests for */ + /* IS_TEXT_UNICODE_CONTROLS and IS_TEXT_UNICODE_REVERSE_CONTROLS */ + /* are not mutually exclusive. Regardless of whether the strings */ + /* contain an indication of endianness, the tests are still */ + /* run if the flag is passed to (Rtl)IsTextUnicode. */ + + /* Test IS_TEXT_UNICODE_CONTROLS flag */ + flags = IS_TEXT_UNICODE_CONTROLS; + ok(!pRtlIsTextUnicode(unicode_no_controls, sizeof(unicode_no_controls), &flags), "Test should not pass on Unicode string lacking control characters.\n"); + ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags); + + flags = IS_TEXT_UNICODE_CONTROLS; + ok(!pRtlIsTextUnicode(be_unicode_no_controls, sizeof(unicode_no_controls), &flags), "Test should not pass on byte-reversed Unicode string lacking control characters.\n"); + ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags); + + flags = IS_TEXT_UNICODE_CONTROLS; + todo_wine + { + ok(pRtlIsTextUnicode(unicode, sizeof(unicode), &flags), "Test should pass on Unicode string lacking control characters.\n"); + ok(flags == IS_TEXT_UNICODE_CONTROLS, "Expected flags 0x04, obtained %x\n", flags); + } + + flags = IS_TEXT_UNICODE_CONTROLS; + ok(!pRtlIsTextUnicode(be_unicode_no_controls, sizeof(unicode_no_controls) + 2, &flags), + "Test should not pass with standard Unicode string.\n"); + ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags); + + flags = IS_TEXT_UNICODE_CONTROLS; + todo_wine + { + ok(pRtlIsTextUnicode(mixed_controls, sizeof(mixed_controls), &flags), "Test should pass on a string containing control characters.\n"); + ok(flags == IS_TEXT_UNICODE_CONTROLS, "Expected flags 0x04, obtained %x\n", flags); + } + + /* Test IS_TEXT_UNICODE_REVERSE_CONTROLS flag */ + flags = IS_TEXT_UNICODE_REVERSE_CONTROLS; + ok(!pRtlIsTextUnicode(be_unicode_no_controls, sizeof(unicode_no_controls), &flags), "Test should not pass on Unicode string lacking control characters.\n"); + ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags); + + flags = IS_TEXT_UNICODE_REVERSE_CONTROLS; + ok(!pRtlIsTextUnicode(unicode_no_controls, sizeof(unicode_no_controls), &flags), "Test should not pass on Unicode string lacking control characters.\n"); + ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags); + + flags = IS_TEXT_UNICODE_REVERSE_CONTROLS; + ok(!pRtlIsTextUnicode(unicode, sizeof(unicode), &flags), "Test should not pass on Unicode string lacking control characters.\n"); + ok(flags == 0, "Expected flags 0x0, obtained %x\n", flags); + + flags = IS_TEXT_UNICODE_REVERSE_CONTROLS; + ok(!pRtlIsTextUnicode(be_unicode, sizeof(unicode) + 2, &flags), + "Test should pass with byte-reversed Unicode string containing control characters.\n"); + todo_wine + ok(flags == IS_TEXT_UNICODE_REVERSE_CONTROLS, "Expected flags 0x40, obtained %x\n", flags); + + flags = IS_TEXT_UNICODE_REVERSE_CONTROLS; + ok(!pRtlIsTextUnicode(mixed_controls, sizeof(mixed_controls), &flags), "Test should pass on a string containing byte-reversed control characters.\n"); + todo_wine + ok(flags == IS_TEXT_UNICODE_REVERSE_CONTROLS, "Expected flags 0x40, obtained %x\n", flags); + + /* Test with flags for both byte-reverse and standard Unicode characters */ + flags = IS_TEXT_UNICODE_CONTROLS | IS_TEXT_UNICODE_REVERSE_CONTROLS; + ok(!pRtlIsTextUnicode(mixed_controls, sizeof(mixed_controls), &flags), "Test should pass on string containing both byte-reversed and standard control characters.\n"); + todo_wine + ok(flags == (IS_TEXT_UNICODE_CONTROLS | IS_TEXT_UNICODE_REVERSE_CONTROLS), "Expected flags 0x44, obtained %x\n", flags); + HeapFree(GetProcessHeap(), 0, be_unicode); + HeapFree(GetProcessHeap(), 0, be_unicode_no_controls); } static const WCHAR szGuid[] = { '{','0','1','0','2','0','3','0','4','-', diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 5977300bdeb..f14085dd216 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -1243,6 +1243,21 @@ done: /*********************************************************************** + * virtual_clear_thread_stack + * + * Clear the stack contents before calling the main entry point, some broken apps need that. + */ +void virtual_clear_thread_stack(void) +{ + void *stack = NtCurrentTeb()->Tib.StackLimit; + size_t size = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit; + + wine_anon_mmap( stack, size, PROT_READ | PROT_WRITE, MAP_FIXED ); + if (force_exec_prot) mprotect( stack, size, PROT_READ | PROT_WRITE | PROT_EXEC ); +} + + +/*********************************************************************** * VIRTUAL_HandleFault */ NTSTATUS VIRTUAL_HandleFault( LPCVOID addr ) diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 72801505694..3df04216f67 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -724,7 +724,7 @@ HRESULT apartment_createwindowifneeded(struct apartment *apt) { HWND hwnd = CreateWindowW(wszAptWinClass, NULL, 0, 0, 0, 0, 0, - 0, 0, OLE32_hInstance, NULL); + HWND_MESSAGE, 0, OLE32_hInstance, NULL); if (!hwnd) { ERR("CreateWindow failed with error %d\n", GetLastError()); @@ -1231,7 +1231,9 @@ HRESULT WINAPI CoDisconnectObject( LPUNKNOWN lpUnk, DWORD reserved ) */ HRESULT WINAPI CoCreateGuid(GUID *pguid) { - return UuidCreate(pguid); + DWORD status = UuidCreate(pguid); + if (status == RPC_S_OK || status == RPC_S_UUID_LOCAL_ONLY) return S_OK; + return HRESULT_FROM_WIN32( status ); } /****************************************************************************** diff --git a/dlls/ole32/enumx.c b/dlls/ole32/enumx.c index ea850926f15..26653014984 100644 --- a/dlls/ole32/enumx.c +++ b/dlls/ole32/enumx.c @@ -25,12 +25,15 @@ #include "windef.h" #include "winbase.h" #include "objbase.h" + +#include "enumx.h" + #include "wine/list.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); -typedef struct tagEnumSTATPROPSETSTG_impl +struct tagEnumSTATPROPSETSTG_impl { const void *vtbl; LONG ref; @@ -38,7 +41,7 @@ typedef struct tagEnumSTATPROPSETSTG_impl struct list *current; ULONG elem_size; GUID riid; -} enumx_impl; +}; /************************************************************************ * enumx_QueryInterface diff --git a/dlls/ole32/ole32_main.c b/dlls/ole32/ole32_main.c index 89878b7323f..4c68321b9f1 100644 --- a/dlls/ole32/ole32_main.c +++ b/dlls/ole32/ole32_main.c @@ -30,6 +30,7 @@ #include "winuser.h" #include "winnls.h" #include "objbase.h" +#include "ole2.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); diff --git a/dlls/ole32/oleobj.c b/dlls/ole32/oleobj.c index 217e01ddcab..b01f59db599 100644 --- a/dlls/ole32/oleobj.c +++ b/dlls/ole32/oleobj.c @@ -32,6 +32,8 @@ #include "wine/debug.h" #include "ole2.h" +#include "compobj_private.h" + WINE_DEFAULT_DEBUG_CHANNEL(ole); #define INITIAL_SINKS 10 diff --git a/dlls/ole32/stg_bigblockfile.c b/dlls/ole32/stg_bigblockfile.c index 2c89a3d5ea3..b0e54e5ef52 100644 --- a/dlls/ole32/stg_bigblockfile.c +++ b/dlls/ole32/stg_bigblockfile.c @@ -412,17 +412,6 @@ void BIGBLOCKFILE_SetSize(LPBIGBLOCKFILE This, ULARGE_INTEGER newSize) } /****************************************************************************** - * BIGBLOCKFILE_GetSize - * - * Returns the size of the file. - * - */ -ULARGE_INTEGER BIGBLOCKFILE_GetSize(LPBIGBLOCKFILE This) -{ - return This->filesize; -} - -/****************************************************************************** * BIGBLOCKFILE_FindPageInList [PRIVATE] * */ diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c index 74a7812f988..3479c184258 100644 --- a/dlls/oleaut32/tests/typelib.c +++ b/dlls/oleaut32/tests/typelib.c @@ -640,7 +640,7 @@ static void test_QueryPathOfRegTypeLib(void) BSTR path; status = UuidCreate(&uid); - ok(!status, "UuidCreate error %08lx\n", status); + ok(!status || status == RPC_S_UUID_LOCAL_ONLY, "UuidCreate error %08lx\n", status); StringFromGUID2(&uid, uid_str, 40); /*trace("GUID: %s\n", wine_dbgstr_w(uid_str));*/ diff --git a/dlls/quartz/avidec.c b/dlls/quartz/avidec.c index e35f144d00b..79fd4d8434b 100644 --- a/dlls/quartz/avidec.c +++ b/dlls/quartz/avidec.c @@ -31,6 +31,7 @@ #include "strmif.h" #include "vfwmsgs.h" #include "vfw.h" +#include "dvdmedia.h" #include @@ -179,35 +180,44 @@ static HRESULT AVIDec_ConnectInput(TransformFilterImpl* pTransformFilter, const /* Check root (GUID w/o FOURCC) */ if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) && - (!memcmp(((const char *)&pmt->subtype)+4, ((const char *)&MEDIATYPE_Video)+4, sizeof(GUID)-4)) && - (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))) + (!memcmp(((const char *)&pmt->subtype)+4, ((const char *)&MEDIATYPE_Video)+4, sizeof(GUID)-4))) { - VIDEOINFOHEADER* format = (VIDEOINFOHEADER*)pmt->pbFormat; - - This->hvid = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, &format->bmiHeader, NULL, ICMODE_DECOMPRESS); + VIDEOINFOHEADER *format1 = (VIDEOINFOHEADER *)pmt->pbFormat; + VIDEOINFOHEADER2 *format2 = (VIDEOINFOHEADER2 *)pmt->pbFormat; + BITMAPINFOHEADER *bmi; + + if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) + bmi = &format1->bmiHeader; + else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) + bmi = &format2->bmiHeader; + else + goto failed; + TRACE("Fourcc: %s\n", debugstr_an((char *)&pmt->subtype.Data1, 4)); + + This->hvid = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, bmi, NULL, ICMODE_DECOMPRESS); if (This->hvid) { AM_MEDIA_TYPE* outpmt = &((OutputPin*)This->tf.ppPins[1])->pin.mtCurrent; const CLSID* outsubtype; DWORD bih_size; - DWORD output_depth = format->bmiHeader.biBitCount; + DWORD output_depth = bmi->biBitCount; DWORD result; - switch(format->bmiHeader.biBitCount) + switch(bmi->biBitCount) { case 32: outsubtype = &MEDIASUBTYPE_RGB32; break; case 24: outsubtype = &MEDIASUBTYPE_RGB24; break; case 16: outsubtype = &MEDIASUBTYPE_RGB565; break; case 8: outsubtype = &MEDIASUBTYPE_RGB8; break; default: - TRACE("Non standard input depth %d, forced ouptut depth to 32\n", format->bmiHeader.biBitCount); + WARN("Non standard input depth %d, forced output depth to 32\n", bmi->biBitCount); outsubtype = &MEDIASUBTYPE_RGB32; output_depth = 32; break; } /* Copy bitmap header from media type to 1 for input and 1 for output */ - bih_size = format->bmiHeader.biSize + format->bmiHeader.biClrUsed * 4; + bih_size = bmi->biSize + bmi->biClrUsed * 4; This->pBihIn = CoTaskMemAlloc(bih_size); if (!This->pBihIn) { @@ -220,25 +230,31 @@ static HRESULT AVIDec_ConnectInput(TransformFilterImpl* pTransformFilter, const hr = E_OUTOFMEMORY; goto failed; } - memcpy(This->pBihIn, &format->bmiHeader, bih_size); - memcpy(This->pBihOut, &format->bmiHeader, bih_size); + memcpy(This->pBihIn, bmi, bih_size); + memcpy(This->pBihOut, bmi, bih_size); /* Update output format as non compressed bitmap */ This->pBihOut->biCompression = 0; This->pBihOut->biBitCount = output_depth; This->pBihOut->biSizeImage = This->pBihOut->biWidth * This->pBihOut->biHeight * This->pBihOut->biBitCount / 8; - + TRACE("Size: %u\n", This->pBihIn->biSize); result = ICDecompressQuery(This->hvid, This->pBihIn, This->pBihOut); if (result != ICERR_OK) { - TRACE("Unable to found a suitable output format (%d)\n", result); + ERR("Unable to found a suitable output format (%d)\n", result); goto failed; } /* Update output media type */ CopyMediaType(outpmt, pmt); outpmt->subtype = *outsubtype; - memcpy(&(((VIDEOINFOHEADER*)outpmt->pbFormat)->bmiHeader), This->pBihOut, This->pBihOut->biSize); + + if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) + memcpy(&(((VIDEOINFOHEADER *)outpmt->pbFormat)->bmiHeader), This->pBihOut, This->pBihOut->biSize); + else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) + memcpy(&(((VIDEOINFOHEADER2 *)outpmt->pbFormat)->bmiHeader), This->pBihOut, This->pBihOut->biSize); + else + assert(0); /* Update buffer size of media samples in output */ ((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = This->pBihOut->biSizeImage; @@ -251,7 +267,7 @@ static HRESULT AVIDec_ConnectInput(TransformFilterImpl* pTransformFilter, const failed: AVIDec_Cleanup(pTransformFilter); - + TRACE("Connection refused\n"); return hr; } diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c index 787ffe75fbf..1bdf390ab5b 100644 --- a/dlls/quartz/dsoundrender.c +++ b/dlls/quartz/dsoundrender.c @@ -42,7 +42,6 @@ static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; static const IBaseFilterVtbl DSoundRender_Vtbl; static const IPinVtbl DSoundRender_InputPin_Vtbl; -static const IMemInputPinVtbl MemInputPin_Vtbl; static const IBasicAudioVtbl IBasicAudio_Vtbl; static const IReferenceClockVtbl IReferenceClock_Vtbl; static const IMediaSeekingVtbl IMediaSeeking_Vtbl; @@ -262,7 +261,7 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample) ERR("Cannot get sample time (%x)\n", hr); if (This->rtLastStop != tStart && (IMediaSample_IsDiscontinuity(pSample) == S_FALSE)) - FIXME("Unexpected discontinuity: Last: %u.%03u, tStart: %u.%03u\n", + WARN("Unexpected discontinuity: Last: %u.%03u, tStart: %u.%03u\n", (DWORD)(This->rtLastStop / 10000000), (DWORD)((This->rtLastStop / 10000)%1000), (DWORD)(tStart / 10000000), (DWORD)((tStart / 10000)%1000)); This->rtLastStop = tStop; @@ -344,7 +343,7 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) piInput.dir = PINDIR_INPUT; piInput.pFilter = (IBaseFilter *)pDSoundRender; lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); - hr = InputPin_Construct(&DSoundRender_InputPin_Vtbl, &piInput, DSoundRender_Sample, pDSoundRender, DSoundRender_QueryAccept, NULL, &pDSoundRender->csFilter, (IPin **)&pDSoundRender->pInputPin); + hr = InputPin_Construct(&DSoundRender_InputPin_Vtbl, &piInput, DSoundRender_Sample, pDSoundRender, DSoundRender_QueryAccept, NULL, &pDSoundRender->csFilter, NULL, (IPin **)&pDSoundRender->pInputPin); if (SUCCEEDED(hr)) { @@ -780,7 +779,7 @@ static HRESULT WINAPI DSoundRender_InputPin_ReceiveConnection(IPin * iface, IPin This->pin.pConnectedTo = pReceivePin; IPin_AddRef(pReceivePin); } - else + else if (hr != VFW_E_ALREADY_CONNECTED) { if (DSImpl->dsbuffer) IDirectSoundBuffer_Release(DSImpl->dsbuffer); @@ -894,19 +893,6 @@ static const IPinVtbl DSoundRender_InputPin_Vtbl = InputPin_NewSegment }; -static const IMemInputPinVtbl MemInputPin_Vtbl = -{ - MemInputPin_QueryInterface, - MemInputPin_AddRef, - MemInputPin_Release, - MemInputPin_GetAllocator, - MemInputPin_NotifyAllocator, - MemInputPin_GetAllocatorRequirements, - MemInputPin_Receive, - MemInputPin_ReceiveMultiple, - MemInputPin_ReceiveCanBlock -}; - /*** IUnknown methods ***/ static HRESULT WINAPI Basicaudio_QueryInterface(IBasicAudio *iface, REFIID riid, diff --git a/dlls/quartz/enumregfilters.c b/dlls/quartz/enumregfilters.c index 2816f08f866..f8d7820d511 100644 --- a/dlls/quartz/enumregfilters.c +++ b/dlls/quartz/enumregfilters.c @@ -152,7 +152,7 @@ static HRESULT WINAPI IEnumRegFiltersImpl_Next(IEnumRegFilters * iface, ULONG cF for(i = 0; i < cFetched; i++) { /* The string in the REGFILTER structure must be allocated in the same block as the REGFILTER structure itself */ - ppRegFilter[i] = CoTaskMemAlloc(sizeof(REGFILTER)+(strlenW(This->RegFilters[i].Name)+1)*sizeof(WCHAR)); + ppRegFilter[i] = CoTaskMemAlloc(sizeof(REGFILTER)+(strlenW(This->RegFilters[This->uIndex + i].Name)+1)*sizeof(WCHAR)); if (!ppRegFilter[i]) { while(i) @@ -162,9 +162,10 @@ static HRESULT WINAPI IEnumRegFiltersImpl_Next(IEnumRegFilters * iface, ULONG cF } return E_OUTOFMEMORY; } - ppRegFilter[i]->Clsid = This->RegFilters[i].Clsid; + ppRegFilter[i]->Clsid = This->RegFilters[This->uIndex + i].Clsid; ppRegFilter[i]->Name = (WCHAR*)((char*)ppRegFilter[i]+sizeof(REGFILTER)); - CopyMemory(ppRegFilter[i]->Name, This->RegFilters[i].Name, (strlenW(This->RegFilters[i].Name)+1)*sizeof(WCHAR)); + CopyMemory(ppRegFilter[i]->Name, This->RegFilters[This->uIndex + i].Name, + (strlenW(This->RegFilters[This->uIndex + i].Name)+1)*sizeof(WCHAR)); } This->uIndex += cFetched; diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index bf929d2cc81..9f6f79a756b 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -156,7 +156,7 @@ typedef struct _IFilterGraphImpl { const IMediaControlVtbl *IMediaControl_vtbl; const IMediaSeekingVtbl *IMediaSeeking_vtbl; const IBasicAudioVtbl *IBasicAudio_vtbl; - const IBasicVideoVtbl *IBasicVideo_vtbl; + const IBasicVideo2Vtbl *IBasicVideo_vtbl; const IVideoWindowVtbl *IVideoWindow_vtbl; const IMediaEventExVtbl *IMediaEventEx_vtbl; const IMediaFilterVtbl *IMediaFilter_vtbl; @@ -166,7 +166,6 @@ typedef struct _IFilterGraphImpl { const IUnknownVtbl * IInner_vtbl; /* IAMGraphStreams */ /* IAMStats */ - /* IBasicVideo2 */ /* IFilterChain */ /* IFilterMapper2 */ /* IGraphVersion */ @@ -237,9 +236,10 @@ static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown * iface, } else if (IsEqualGUID(&IID_IBasicAudio, riid)) { *ppvObj = &(This->IBasicAudio_vtbl); TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj); - } else if (IsEqualGUID(&IID_IBasicVideo, riid)) { + } else if (IsEqualGUID(&IID_IBasicVideo, riid) || + IsEqualGUID(&IID_IBasicVideo2, riid)) { *ppvObj = &(This->IBasicVideo_vtbl); - TRACE(" returning IBasicVideo interface (%p)\n", *ppvObj); + TRACE(" returning IBasicVideo2 interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IVideoWindow, riid)) { *ppvObj = &(This->IVideoWindow_vtbl); TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj); @@ -279,22 +279,24 @@ static ULONG WINAPI FilterGraphInner_AddRef(IUnknown * iface) { return ref; } -static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface) { +static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface) +{ ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); - + TRACE("(%p)->(): new ref = %d\n", This, ref); - + if (ref == 0) { int i; IMediaControl_Stop((IMediaControl*)&(This->IMediaControl_vtbl)); - if (This->refClock) - IReferenceClock_Release(This->refClock); while (This->nFilters) IFilterGraph2_RemoveFilter((IFilterGraph2*)This, This->ppFiltersInGraph[0]); + if (This->refClock) + IReferenceClock_Release(This->refClock); + for (i = 0; i < This->nItfCacheEntries; i++) { if (This->ItfCacheEntries[i].iface) @@ -439,8 +441,8 @@ static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, return hr; } -static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, - IBaseFilter *pFilter) { +static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *pFilter) +{ ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); int i; HRESULT hr = E_FAIL; @@ -453,12 +455,21 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, { if (This->ppFiltersInGraph[i] == pFilter) { - IEnumPins *penumpins; - IBaseFilter_Stop(pFilter); + IEnumPins *penumpins = NULL; + FILTER_STATE state; + + TRACE("Removing filter %s\n", debugstr_w(This->pFilterNames[i])); + IBaseFilter_GetState(pFilter, 0, &state); + if (state == State_Running) + IBaseFilter_Pause(pFilter); + if (state != State_Stopped) + IBaseFilter_Stop(pFilter); + hr = IBaseFilter_EnumPins(pFilter, &penumpins); if (SUCCEEDED(hr)) { IPin *ppin; - while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK) { + while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK) + { IPin *victim = NULL; HRESULT h; IPin_ConnectedTo(ppin, &victim); @@ -470,6 +481,10 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, { PIN_INFO pinfo; IPin_QueryPinInfo(victim, &pinfo); + + IBaseFilter_GetState(pinfo.pFilter, 0, &state); + if (state == State_Running) + IBaseFilter_Pause(pinfo.pFilter); IBaseFilter_Stop(pinfo.pFilter); IBaseFilter_Release(pinfo.pFilter); h = IPin_Disconnect(victim); @@ -543,6 +558,83 @@ static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface, return VFW_E_NOT_FOUND; } +/* Don't allow a circular connection to form, return VFW_E_CIRCULAR_GRAPH if this would be the case. + * A circular connection will be formed if from the filter of the output pin, the input pin can be reached + */ +static HRESULT WINAPI CheckCircularConnection(IFilterGraphImpl *This, IPin *out, IPin *in) +{ +#if 1 + HRESULT hr; + PIN_INFO info_out, info_in; + + hr = IPin_QueryPinInfo(out, &info_out); + if (FAILED(hr)) + return hr; + if (info_out.dir != PINDIR_OUTPUT) + { + IBaseFilter_Release(info_out.pFilter); + return E_UNEXPECTED; + } + + hr = IPin_QueryPinInfo(in, &info_in); + if (SUCCEEDED(hr)) + IBaseFilter_Release(info_in.pFilter); + if (FAILED(hr)) + goto out; + if (info_in.dir != PINDIR_INPUT) + { + hr = E_UNEXPECTED; + goto out; + } + + if (info_out.pFilter == info_in.pFilter) + hr = VFW_E_CIRCULAR_GRAPH; + else + { + IEnumPins *enumpins; + IPin *test; + + hr = IBaseFilter_EnumPins(info_out.pFilter, &enumpins); + if (FAILED(hr)) + goto out; + + IEnumPins_Reset(enumpins); + while ((hr = IEnumPins_Next(enumpins, 1, &test, NULL)) == S_OK) + { + PIN_DIRECTION dir = PINDIR_OUTPUT; + IPin_QueryDirection(test, &dir); + if (dir == PINDIR_INPUT) + { + IPin *victim = NULL; + IPin_ConnectedTo(test, &victim); + if (victim) + { + hr = CheckCircularConnection(This, victim, in); + IPin_Release(victim); + if (FAILED(hr)) + { + IPin_Release(test); + break; + } + } + } + IPin_Release(test); + } + IEnumPins_Release(enumpins); + } + +out: + IBaseFilter_Release(info_out.pFilter); + if (FAILED(hr)) + ERR("Checking filtergraph returned %08x, something's not right!\n", hr); + return hr; +#else + /* Debugging filtergraphs not enabled */ + return S_OK; +#endif +} + + /* NOTE: despite the implication, it doesn't matter which * way round you put in the input and output pins */ static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, @@ -581,9 +673,17 @@ static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, if (SUCCEEDED(hr)) { if (dir == PINDIR_INPUT) - hr = IPin_Connect(ppinOut, ppinIn, pmt); + { + hr = CheckCircularConnection(This, ppinOut, ppinIn); + if (SUCCEEDED(hr)) + hr = IPin_Connect(ppinOut, ppinIn, pmt); + } else - hr = IPin_Connect(ppinIn, ppinOut, pmt); + { + hr = CheckCircularConnection(This, ppinIn, ppinOut); + if (SUCCEEDED(hr)) + hr = IPin_Connect(ppinIn, ppinOut, pmt); + } } return hr; @@ -615,8 +715,8 @@ static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface, return hr; } -static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, - IPin *ppin) { +static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, IPin *ppin) +{ ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); TRACE("(%p/%p)->(%p)\n", This, iface, ppin); @@ -735,9 +835,8 @@ static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPi } /*** IGraphBuilder methods ***/ -static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, - IPin *ppinOut, - IPin *ppinIn) { +static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn) +{ ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); HRESULT hr; AM_MEDIA_TYPE* mt; @@ -751,12 +850,13 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, ULONG pin; PIN_INFO PinInfo; CLSID FilterCLSID; + PIN_DIRECTION dir; TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn); if (TRACE_ON(quartz)) { - hr = IPin_QueryPinInfo(ppinIn, &PinInfo); + hr = IPin_QueryPinInfo(ppinIn, &PinInfo); if (FAILED(hr)) return hr; @@ -771,12 +871,29 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IBaseFilter_Release(PinInfo.pFilter); } + hr = IPin_QueryDirection(ppinOut, &dir); + if (FAILED(hr)) + return hr; + + if (dir == PINDIR_INPUT) + { + IPin *temp; + + temp = ppinIn; + ppinIn = ppinOut; + ppinOut = temp; + } + + hr = CheckCircularConnection(This, ppinOut, ppinIn); + if (FAILED(hr)) + return hr; + /* Try direct connection first */ hr = IPin_Connect(ppinOut, ppinIn, NULL); if (SUCCEEDED(hr)) { return S_OK; } - TRACE("Direct connection failed, trying to insert other filters\n"); + TRACE("Direct connection failed, trying to render using extra filters\n"); hr = IPin_QueryPinInfo(ppinIn, &PinInfo); if (FAILED(hr)) @@ -791,18 +908,19 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, * filter to the minor mediatype of input pin of the renderer */ hr = IPin_EnumMediaTypes(ppinOut, &penummt); if (FAILED(hr)) { - ERR("EnumMediaTypes (%x)\n", hr); + WARN("EnumMediaTypes (%x)\n", hr); return hr; } hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt); if (FAILED(hr)) { - ERR("IEnumMediaTypes_Next (%x)\n", hr); + WARN("IEnumMediaTypes_Next (%x)\n", hr); return hr; } - if (!nbmt) { - ERR("No media type found!\n"); + if (!nbmt) + { + WARN("No media type found!\n"); return S_OK; } TRACE("MajorType %s\n", debugstr_guid(&mt->majortype)); @@ -813,10 +931,11 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, tab[1] = mt->subtype; hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL); if (FAILED(hr)) { - ERR("Unable to enum filters (%x)\n", hr); + WARN("Unable to enum filters (%x)\n", hr); return hr; } - + + hr = VFW_E_CANNOT_RENDER; while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK) { VARIANT var; @@ -828,7 +947,7 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, hr = GetFilterInfo(pMoniker, &clsid, &var); IMoniker_Release(pMoniker); if (FAILED(hr)) { - ERR("Unable to retrieve filter info (%x)\n", hr); + WARN("Unable to retrieve filter info (%x)\n", hr); goto error; } @@ -839,13 +958,13 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter); if (FAILED(hr)) { - ERR("Unable to create filter (%x), trying next one\n", hr); + WARN("Unable to create filter (%x), trying next one\n", hr); goto error; } hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal)); if (FAILED(hr)) { - ERR("Unable to add filter (%x)\n", hr); + WARN("Unable to add filter (%x)\n", hr); IBaseFilter_Release(pfilter); pfilter = NULL; goto error; @@ -853,7 +972,7 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, hr = IBaseFilter_EnumPins(pfilter, &penumpins); if (FAILED(hr)) { - ERR("Enumpins (%x)\n", hr); + WARN("Enumpins (%x)\n", hr); goto error; } @@ -861,11 +980,11 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IEnumPins_Release(penumpins); if (FAILED(hr)) { - ERR("Next (%x)\n", hr); + WARN("Obtaining next pin: (%x)\n", hr); goto error; } if (pin == 0) { - ERR("No Pin\n"); + WARN("Cannot use this filter: no pins\n"); goto error; } @@ -876,21 +995,38 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, } TRACE("Successfully connected to filter, follow chain...\n"); - /* Render all output pins of the filter by calling IFilterGraph2_Render on each of them */ + /* Render all output pins of the filter by calling IFilterGraph2_Connect on each of them */ hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb); if (SUCCEEDED(hr)) { int i; if (nb == 0) { + IPin_Disconnect(ppinfilter); IPin_Disconnect(ppinOut); goto error; } TRACE("pins to consider: %d\n", nb); - for(i = 0; i < nb; i++) { + for(i = 0; i < nb; i++) + { + LPWSTR pinname = NULL; + TRACE("Processing pin %d\n", i); - hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn); + + hr = IPin_QueryId(ppins[i], &pinname); + if (SUCCEEDED(hr)) + { + if (pinname[0] == '~') + { + TRACE("Pinname=%s, skipping\n", debugstr_w(pinname)); + hr = E_FAIL; + } + else + hr = IFilterGraph2_Connect(iface, ppins[i], ppinIn); + CoTaskMemFree(pinname); + } + if (FAILED(hr)) { - TRACE("Cannot render pin %p (%x)\n", ppinfilter, hr); + TRACE("Cannot connect pin %p (%x)\n", ppinfilter, hr); } IPin_Release(ppins[i]); if (SUCCEEDED(hr)) break; @@ -899,6 +1035,13 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, CoTaskMemFree(ppins); IPin_Release(ppinfilter); IBaseFilter_Release(pfilter); + if (FAILED(hr)) + { + IPin_Disconnect(ppinfilter); + IPin_Disconnect(ppinOut); + IFilterGraph2_RemoveFilter(iface, pfilter); + continue; + } break; } @@ -912,12 +1055,85 @@ error: IEnumMediaTypes_Release(penummt); DeleteMediaType(mt); - - return S_OK; + + TRACE("--> %08x\n", hr); + return SUCCEEDED(hr) ? S_OK : hr; +} + +static HRESULT WINAPI FilterGraph2_RenderRecurse(IFilterGraphImpl *This, IPin *ppinOut) +{ + /* This pin has been connected now, try to call render on all pins that aren't connected */ + IPin *to = NULL; + PIN_INFO info; + IEnumPins *enumpins = NULL; + BOOL renderany = FALSE; + BOOL renderall = TRUE; + + IPin_QueryPinInfo(ppinOut, &info); + + IBaseFilter_EnumPins(info.pFilter, &enumpins); + /* Don't need to hold a reference, IEnumPins does */ + IBaseFilter_Release(info.pFilter); + + IEnumPins_Reset(enumpins); + while (IEnumPins_Next(enumpins, 1, &to, NULL) == S_OK) + { + PIN_DIRECTION dir = PINDIR_INPUT; + + IPin_QueryDirection(to, &dir); + + if (dir == PINDIR_OUTPUT) + { + IPin *out = NULL; + + IPin_ConnectedTo(to, &out); + if (!out) + { + HRESULT hr; + hr = IFilterGraph2_Render((IFilterGraph2 *)&This->IFilterGraph2_vtbl, to); + if (SUCCEEDED(hr)) + renderany = TRUE; + else + renderall = FALSE; + } + else + IPin_Release(out); + } + + IPin_Release(to); + } + + IEnumPins_Release(enumpins); + + if (renderall) + return S_OK; + + if (renderany) + return VFW_S_PARTIAL_RENDER; + + return VFW_E_CANNOT_RENDER; } -static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, - IPin *ppinOut) { +/* Ogg hates me if I create a direct rendering method + * + * It can only connect to a pin properly once, so use a recursive method that does + * + * +----+ --- (PIN 1) (Render is called on this pin) + * | | + * +----+ --- (PIN 2) + * + * Enumerate possible renderers that EXACTLY match the requested type + * + * If none is available, try to add intermediate filters that can connect to the input pin + * then call Render on that intermediate pin's output pins + * if it succeeds: Render returns success, if it doesn't, the intermediate filter is removed, + * and another filter that can connect to the input pin is tried + * if we run out of filters that can, give up and return VFW_E_CANNOT_RENDER + * It's recursive, but fun! + */ + +static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut) +{ ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); IEnumMediaTypes* penummt; AM_MEDIA_TYPE* mt; @@ -925,9 +1141,12 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, HRESULT hr; IEnumMoniker* pEnumMoniker; - GUID tab[2]; + GUID tab[4]; ULONG nb; IMoniker* pMoniker; + INT x; + + BOOL final = FALSE; TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut); @@ -943,34 +1162,120 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IBaseFilter_Release(PinInfo.pFilter); } + /* Try to find out if there is a renderer for the specified subtype already, and use that + */ + EnterCriticalSection(&This->cs); + for (x = 0; x < This->nFilters; ++x) + { + IEnumPins *enumpins = NULL; + IPin *pin = NULL; + + hr = IBaseFilter_EnumPins(This->ppFiltersInGraph[x], &enumpins); + + if (FAILED(hr) || !enumpins) + continue; + + IEnumPins_Reset(enumpins); + while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK) + { + IPin *to = NULL; + PIN_DIRECTION dir = PINDIR_OUTPUT; + + IPin_QueryDirection(pin, &dir); + if (dir != PINDIR_INPUT) + { + IPin_Release(pin); + continue; + } + IPin_ConnectedTo(pin, &to); + + if (to == NULL) + { + hr = IPin_Connect(ppinOut, pin, NULL); + if (SUCCEEDED(hr)) + { + TRACE("Connected succesfully %p/%p, %08x look if we should render more!\n", ppinOut, pin, hr); + IPin_Release(pin); + + hr = FilterGraph2_RenderRecurse(This, pin); + if (FAILED(hr)) + { + IPin_Disconnect(ppinOut); + IPin_Disconnect(pin); + continue; + } + IEnumPins_Release(enumpins); + LeaveCriticalSection(&This->cs); + return hr; + } + WARN("Could not connect!\n"); + } + else + IPin_Release(to); + + IPin_Release(pin); + } + IEnumPins_Release(enumpins); + } + + LeaveCriticalSection(&This->cs); + hr = IPin_EnumMediaTypes(ppinOut, &penummt); if (FAILED(hr)) { - ERR("EnumMediaTypes (%x)\n", hr); + WARN("EnumMediaTypes (%x)\n", hr); return hr; } - while(1) + IEnumMediaTypes_Reset(penummt); + + /* Looks like no existing renderer of the kind exists + * Try adding new ones + */ + tab[0] = tab[1] = GUID_NULL; + while (SUCCEEDED(hr)) { hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt); if (FAILED(hr)) { - ERR("IEnumMediaTypes_Next (%x)\n", hr); - return hr; + WARN("IEnumMediaTypes_Next (%x)\n", hr); + break; } - if (!nbmt) + if (!nbmt && !final) + { + final = TRUE; + tab[0] = tab[1] = GUID_NULL; + IEnumMediaTypes_Reset(penummt); + continue; + } + else if (!nbmt) + { + hr = VFW_E_CANNOT_RENDER; break; - TRACE("MajorType %s\n", debugstr_guid(&mt->majortype)); - TRACE("SubType %s\n", debugstr_guid(&mt->subtype)); + } + else + { + TRACE("MajorType %s\n", debugstr_guid(&mt->majortype)); + TRACE("SubType %s\n", debugstr_guid(&mt->subtype)); - /* Try to find a suitable renderer with the same media type */ - tab[0] = mt->majortype; - tab[1] = GUID_NULL; - hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, TRUE, FALSE, 0, NULL, NULL, NULL); - if (FAILED(hr)) { - ERR("Unable to enum filters (%x)\n", hr); - return hr; + /* Only enumerate once, this doesn't account for all previous ones, but this should be enough nonetheless */ + if (IsEqualIID(&tab[0], &mt->majortype) && IsEqualIID(&tab[0], &mt->majortype)) + { + DeleteMediaType(mt); + continue; + } + + /* Try to find a suitable renderer with the same media type */ + tab[0] = mt->majortype; + tab[1] = mt->subtype; + hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, !final, FALSE, 0, NULL, NULL, NULL); + if (FAILED(hr)) + { + WARN("Unable to enum filters (%x)\n", hr); + break; + } } + hr = E_FAIL; - while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK) + while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK) { VARIANT var; GUID clsid; @@ -982,19 +1287,20 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, hr = GetFilterInfo(pMoniker, &clsid, &var); IMoniker_Release(pMoniker); if (FAILED(hr)) { - ERR("Unable to retrieve filter info (%x)\n", hr); + WARN("Unable to retrieve filter info (%x)\n", hr); goto error; } hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter); - if (FAILED(hr)) { - ERR("Unable to create filter (%x), trying next one\n", hr); - goto error; + if (FAILED(hr)) + { + WARN("Unable to create filter (%x), trying next one\n", hr); + goto error; } hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal)); if (FAILED(hr)) { - ERR("Unable to add filter (%x)\n", hr); + WARN("Unable to add filter (%x)\n", hr); IBaseFilter_Release(pfilter); pfilter = NULL; goto error; @@ -1002,30 +1308,36 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, hr = IBaseFilter_EnumPins(pfilter, &penumpins); if (FAILED(hr)) { - ERR("Splitter Enumpins (%x)\n", hr); + WARN("Splitter Enumpins (%x)\n", hr); goto error; } hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin); IEnumPins_Release(penumpins); if (FAILED(hr)) { - ERR("Next (%x)\n", hr); - goto error; + WARN("Next (%x)\n", hr); + goto error; } if (pin == 0) { - ERR("No Pin\n"); - goto error; + WARN("No Pin\n"); + hr = E_FAIL; + goto error; } - /* Connect the pin to render to the renderer */ - hr = IFilterGraph2_Connect(iface, ppinOut, ppinfilter); + /* Connect the pin to the "Renderer" */ + hr = IPin_Connect(ppinOut, ppinfilter, NULL); + IPin_Release(ppinfilter); + if (FAILED(hr)) { - TRACE("Unable to connect to renderer (%x)\n", hr); - IPin_Release(ppinfilter); + WARN("Unable to connect %s to renderer (%x)\n", debugstr_w(V_UNION(&var, bstrVal)), hr); + goto error; + } + TRACE("Connected, recursing %s\n", debugstr_w(V_UNION(&var, bstrVal))); + hr = FilterGraph2_RenderRecurse(This, ppinfilter); + if (FAILED(hr)) { + WARN("Unable to connect recursively (%x)\n", hr); goto error; } - IPin_Release(ppinfilter); IBaseFilter_Release(pfilter); - pfilter = NULL; break; error: @@ -1033,37 +1345,32 @@ error: IFilterGraph2_RemoveFilter(iface, pfilter); IBaseFilter_Release(pfilter); } - } - - DeleteMediaType(mt); - break; + if (!FAILED(hr)) DebugBreak(); + } + + if (nbmt) + DeleteMediaType(mt); + if (SUCCEEDED(hr)) + break; + hr = S_OK; } IEnumMediaTypes_Release(penummt); - - return S_OK; + return hr; } static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, - LPCWSTR lpcwstrFile, - LPCWSTR lpcwstrPlayList) { + LPCWSTR lpcwstrFile, + LPCWSTR lpcwstrPlayList) +{ ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); static const WCHAR string[] = {'R','e','a','d','e','r',0}; IBaseFilter* preader = NULL; - IBaseFilter* psplitter = NULL; IPin* ppinreader = NULL; - IPin* ppinsplitter = NULL; - IEnumPins* penumpins; - ULONG pin; + IEnumPins* penumpins = NULL; HRESULT hr; - IEnumMoniker* pEnumMoniker = NULL; - GUID tab[2]; - IPin** ppins = NULL; - ULONG nb; - IMoniker* pMoniker; - IFileSourceFilter* pfile = NULL; - AM_MEDIA_TYPE mt; - WCHAR* filename; + BOOL partial = FALSE; + HRESULT any = FALSE; TRACE("(%p/%p)->(%s, %s)\n", This, iface, debugstr_w(lpcwstrFile), debugstr_w(lpcwstrPlayList)); @@ -1071,134 +1378,47 @@ static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, return E_INVALIDARG; hr = IFilterGraph2_AddSourceFilter(iface, lpcwstrFile, string, &preader); - - /* Retrieve file media type */ - if (SUCCEEDED(hr)) - hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (LPVOID*)&pfile); - if (SUCCEEDED(hr)) { - hr = IFileSourceFilter_GetCurFile(pfile, &filename, &mt); - IFileSourceFilter_Release(pfile); - } - - if (SUCCEEDED(hr)) - hr = IBaseFilter_EnumPins(preader, &penumpins); - if (SUCCEEDED(hr)) { - hr = IEnumPins_Next(penumpins, 1, &ppinreader, &pin); - IEnumPins_Release(penumpins); - } - - if (SUCCEEDED(hr)) { - tab[0] = mt.majortype; - tab[1] = mt.subtype; - hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL); - } - if (FAILED(hr)) - { - if (ppinreader) - IPin_Release(ppinreader); - if (pEnumMoniker) - IEnumMoniker_Release(pEnumMoniker); - if (preader) { - IFilterGraph2_RemoveFilter(iface, preader); - IBaseFilter_Release(preader); - } return hr; - } - hr = VFW_E_CANNOT_RENDER; - while(IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK) + if (SUCCEEDED(hr)) + hr = IBaseFilter_EnumPins(preader, &penumpins); + if (SUCCEEDED(hr)) { - VARIANT var; - GUID clsid; - - hr = GetFilterInfo(pMoniker, &clsid, &var); - IMoniker_Release(pMoniker); - if (FAILED(hr)) { - ERR("Unable to retrieve filter info (%x)\n", hr); - continue; - } - - hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&psplitter); - if (FAILED(hr)) { - ERR("Unable to create filter (%x), trying next one\n", hr); - continue; - } - - hr = IFilterGraph2_AddFilter(iface, psplitter, V_UNION(&var, bstrVal)); - if (FAILED(hr)) { - ERR("Unable add filter (%x)\n", hr); - IBaseFilter_Release(psplitter); - continue; - } - - /* Connect file source and splitter filters together */ - /* Make the splitter analyze incoming data */ - - hr = IBaseFilter_EnumPins(psplitter, &penumpins); - if (SUCCEEDED(hr)) { - hr = IEnumPins_Next(penumpins, 1, &ppinsplitter, &pin); - IEnumPins_Release(penumpins); - } - - if (SUCCEEDED(hr)) - hr = IPin_Connect(ppinreader, ppinsplitter, NULL); - - /* Make sure there's some output pins in the filter */ - if (SUCCEEDED(hr)) - hr = GetInternalConnections(psplitter, ppinsplitter, &ppins, &nb); - if (SUCCEEDED(hr)) { - if(nb == 0) { - IPin_Disconnect(ppinreader); - TRACE("No output pins found in filter\n"); - hr = VFW_E_CANNOT_RENDER; - } - } - - if (ppinsplitter) - IPin_Release(ppinsplitter); - ppinsplitter = NULL; + while (IEnumPins_Next(penumpins, 1, &ppinreader, NULL) == S_OK) + { + PIN_DIRECTION dir; - if (SUCCEEDED(hr)) { - TRACE("Successfully connected to filter\n"); - break; - } + IPin_QueryDirection(ppinreader, &dir); + if (dir == PINDIR_OUTPUT) + { + INT i; - TRACE("Cannot connect to filter (%x), trying next one\n", hr); + hr = IFilterGraph2_Render(iface, ppinreader); + ERR("Render %08x\n", hr); - if (ppins) { - CoTaskMemFree(ppins); - ppins = NULL; - } - IFilterGraph2_RemoveFilter(iface, psplitter); - IBaseFilter_Release(psplitter); - psplitter = NULL; - } + for (i = 0; i < This->nFilters; ++i) + FIXME("Filters in chain: %s\n", debugstr_w(This->pFilterNames[i])); - /* Render all output pin of the splitter by calling IFilterGraph2_Render on each of them */ - if (SUCCEEDED(hr)) { - int partial = 0; - int i; - TRACE("pins to consider: %d\n", nb); - for(i = 0; i < nb; i++) { - TRACE("Processing pin %d\n", i); - hr = IFilterGraph2_Render(iface, ppins[i]); - if (FAILED(hr)) { - ERR("Cannot render pin %p (%x)\n", ppins[i], hr); - partial = 1; + if (SUCCEEDED(hr)) + any = TRUE; + if (hr != S_OK) + partial = TRUE; } - IPin_Release(ppins[i]); + IPin_Release(ppinreader); } - CoTaskMemFree(ppins); + IEnumPins_Release(penumpins); - hr = (partial ? VFW_S_PARTIAL_RENDER : S_OK); + if (!any) + hr = VFW_E_CANNOT_RENDER; + else if (partial) + hr = VFW_S_PARTIAL_RENDER; + else + hr = S_OK; } - - IPin_Release(ppinreader); IBaseFilter_Release(preader); - if (psplitter) - IBaseFilter_Release(psplitter); + TRACE("--> %08x\n", hr); return hr; } @@ -1490,9 +1710,9 @@ static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface, return S_OK; } -typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *); +typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *, DWORD_PTR data); -static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter) +static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter, DWORD_PTR data) { HRESULT hr; IPin* pInputPin; @@ -1529,7 +1749,7 @@ static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundF /* Explore the graph downstream from this pin * FIXME: We should prevent exploring from a pin more than once. This can happens when * several input pins are connected to the same output (a MUX for instance). */ - ExploreGraph(pGraph, ppPins[i], FoundFilter); + ExploreGraph(pGraph, ppPins[i], FoundFilter, data); IPin_Release(ppPins[i]); } @@ -1537,14 +1757,15 @@ static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundF } TRACE("Doing stuff with filter %p\n", PinInfo.pFilter); - FoundFilter(PinInfo.pFilter); + FoundFilter(PinInfo.pFilter, data); } if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter); return hr; } -static HRESULT WINAPI SendRun(IBaseFilter *pFilter) { +static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data) +{ LONGLONG time = 0; IReferenceClock *clock = NULL; @@ -1563,15 +1784,40 @@ static HRESULT WINAPI SendRun(IBaseFilter *pFilter) { return IBaseFilter_Run(pFilter, time); } -static HRESULT WINAPI SendPause(IBaseFilter *pFilter) { +static HRESULT WINAPI SendPause(IBaseFilter *pFilter, DWORD_PTR data) +{ return IBaseFilter_Pause(pFilter); } -static HRESULT WINAPI SendStop(IBaseFilter *pFilter) { +static HRESULT WINAPI SendStop(IBaseFilter *pFilter, DWORD_PTR data) +{ return IBaseFilter_Stop(pFilter); } -static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter) { +static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data) +{ + FILTER_STATE state; + DWORD time_end = data; + DWORD time_now = GetTickCount(); + LONG wait; + + if (time_end == INFINITE) + { + wait = INFINITE; + } + else if (time_end > time_now) + { + wait = time_end - time_now; + } + else + wait = 0; + + return IBaseFilter_GetState(pFilter, wait, &state); +} + + +static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter, DWORD_PTR data) +{ ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); int i; IBaseFilter* pfilter; @@ -1615,10 +1861,10 @@ static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK) { /* Explore the graph downstream from this pin */ - ExploreGraph(This, pPin, FoundFilter); + ExploreGraph(This, pPin, FoundFilter, data); IPin_Release(pPin); } - FoundFilter(pfilter); + FoundFilter(pfilter, data); } IEnumPins_Release(pEnum); } @@ -1644,7 +1890,7 @@ static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) { } else This->position = This->start_time = 0; - SendFilterMessage(iface, SendRun); + SendFilterMessage(iface, SendRun, 0); This->state = State_Running; LeaveCriticalSection(&This->cs); return S_FALSE; @@ -1667,7 +1913,7 @@ static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface) { This->position += time - This->start_time; } - SendFilterMessage(iface, SendPause); + SendFilterMessage(iface, SendPause, 0); This->state = State_Paused; LeaveCriticalSection(&This->cs); return S_FALSE; @@ -1687,8 +1933,8 @@ static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) { This->position += time - This->start_time; } - if (This->state == State_Running) SendFilterMessage(iface, SendPause); - SendFilterMessage(iface, SendStop); + if (This->state == State_Running) SendFilterMessage(iface, SendPause, 0); + SendFilterMessage(iface, SendStop, 0); This->state = State_Stopped; LeaveCriticalSection(&This->cs); return S_OK; @@ -1698,8 +1944,9 @@ static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, LONG msTimeout, OAFilterState *pfs) { ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); + DWORD end; - TRACE("(%p/%p)->(%d, %p): semi-stub !!!\n", This, iface, msTimeout, pfs); + TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pfs); if (!pfs) return E_POINTER; @@ -1707,6 +1954,20 @@ static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, EnterCriticalSection(&This->cs); *pfs = This->state; + if (msTimeout > 0) + { + end = GetTickCount() + msTimeout; + } + else if (msTimeout < 0) + { + end = INFINITE; + } + else + { + end = 0; + } + if (end) + SendFilterMessage(iface, SendGetState, end); LeaveCriticalSection(&This->cs); @@ -2621,7 +2882,7 @@ static const IBasicAudioVtbl IBasicAudio_VTable = }; /*** IUnknown methods ***/ -static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, REFIID riid, LPVOID*ppvObj) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); @@ -2631,7 +2892,7 @@ static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo *iface, return Filtergraph_QueryInterface(This, riid, ppvObj); } -static ULONG WINAPI BasicVideo_AddRef(IBasicVideo *iface) { +static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); TRACE("(%p/%p)->()\n", This, iface); @@ -2639,7 +2900,7 @@ static ULONG WINAPI BasicVideo_AddRef(IBasicVideo *iface) { return Filtergraph_AddRef(This); } -static ULONG WINAPI BasicVideo_Release(IBasicVideo *iface) { +static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); TRACE("(%p/%p)->()\n", This, iface); @@ -2648,7 +2909,7 @@ static ULONG WINAPI BasicVideo_Release(IBasicVideo *iface) { } /*** IDispatch methods ***/ -static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, UINT*pctinfo) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2668,7 +2929,7 @@ static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo) { @@ -2690,7 +2951,7 @@ static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, @@ -2714,7 +2975,7 @@ static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, DISPID dispIdMember, REFIID riid, LCID lcid, @@ -2742,7 +3003,7 @@ static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo *iface, } /*** IBasicVideo methods ***/ -static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, REFTIME *pAvgTimePerFrame) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2762,7 +3023,7 @@ static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, long *pBitRate) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2782,7 +3043,7 @@ static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, long *pBitErrorRate) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2802,7 +3063,7 @@ static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, long *pVideoWidth) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2822,7 +3083,7 @@ static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, long *pVideoHeight) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2842,7 +3103,7 @@ static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, long SourceLeft) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2862,7 +3123,7 @@ static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, long *pSourceLeft) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2882,7 +3143,7 @@ static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, long SourceWidth) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2902,7 +3163,7 @@ static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, long *pSourceWidth) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2922,7 +3183,7 @@ static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, long SourceTop) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2942,7 +3203,7 @@ static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, long *pSourceTop) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2962,7 +3223,7 @@ static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, long SourceHeight) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -2982,7 +3243,7 @@ static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, long *pSourceHeight) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -3002,7 +3263,7 @@ static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, long DestinationLeft) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -3022,7 +3283,7 @@ static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, long *pDestinationLeft) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -3042,7 +3303,7 @@ static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, long DestinationWidth) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -3062,7 +3323,7 @@ static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, long *pDestinationWidth) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -3082,7 +3343,7 @@ static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, long DestinationTop) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -3102,7 +3363,7 @@ static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, long *pDestinationTop) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -3122,7 +3383,7 @@ static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, long DestinationHeight) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -3142,7 +3403,7 @@ static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface, long *pDestinationHeight) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; @@ -3162,7 +3423,7 @@ static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, long Left, long Top, long Width, @@ -3185,7 +3446,7 @@ static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, long *pLeft, long *pTop, long *pWidth, @@ -3208,7 +3469,7 @@ static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo *iface) { +static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; HRESULT hr; @@ -3227,7 +3488,7 @@ static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo *iface) { return hr; } -static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, long Left, long Top, long Width, @@ -3250,7 +3511,7 @@ static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, long *pLeft, long *pTop, long *pWidth, @@ -3273,7 +3534,7 @@ static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo *iface) { +static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; HRESULT hr; @@ -3292,7 +3553,7 @@ static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo *ifac return hr; } -static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, long *pWidth, long *pHeight) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); @@ -3313,7 +3574,7 @@ static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, long StartIndex, long Entries, long *pRetrieved, @@ -3336,7 +3597,7 @@ static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo *iface, +static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, long *pBufferSize, long *pDIBImage) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); @@ -3357,7 +3618,7 @@ static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo *iface, return hr; } -static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo *iface) { +static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; HRESULT hr; @@ -3376,7 +3637,7 @@ static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo *iface) { return hr; } -static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo *iface) { +static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface) { ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); IBasicVideo* pBasicVideo; HRESULT hr; @@ -3395,8 +3656,26 @@ static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo *iface) { return hr; } +static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX, LONG *plAspectY) { + ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); + IBasicVideo2 *pBasicVideo2; + HRESULT hr; + + TRACE("(%p/%p)->()\n", This, iface); + + EnterCriticalSection(&This->cs); -static const IBasicVideoVtbl IBasicVideo_VTable = + hr = GetTargetInterface(This, &IID_IBasicVideo2, (LPVOID*)&pBasicVideo2); + + if (hr == S_OK) + hr = BasicVideo2_GetPreferredAspectRatio(iface, plAspectX, plAspectY); + + LeaveCriticalSection(&This->cs); + + return hr; +} + +static const IBasicVideo2Vtbl IBasicVideo_VTable = { BasicVideo_QueryInterface, BasicVideo_AddRef, @@ -3436,7 +3715,8 @@ static const IBasicVideoVtbl IBasicVideo_VTable = BasicVideo_GetVideoPaletteEntries, BasicVideo_GetCurrentImage, BasicVideo_IsUsingDefaultSource, - BasicVideo_IsUsingDefaultDestination + BasicVideo_IsUsingDefaultDestination, + BasicVideo2_GetPreferredAspectRatio }; @@ -4908,10 +5188,20 @@ static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, HANDLE hAbortEvent) { ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + HRESULT hr; - FIXME("(%p)->(%p, %p, %x, %p): stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent); - - return E_NOTIMPL; + WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent); + + if (hAbortEvent) + FIXME("The parameter hAbortEvent is not handled!\n"); + + EnterCriticalSection(&This->cs); + + hr = IGraphConfigCallback_Reconfigure(pCallback, pvContext, dwFlags); + + LeaveCriticalSection(&This->cs); + + return hr; } static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface, diff --git a/dlls/quartz/filtermapper.c b/dlls/quartz/filtermapper.c index eeba0b13b33..da6d59f0450 100644 --- a/dlls/quartz/filtermapper.c +++ b/dlls/quartz/filtermapper.c @@ -1040,7 +1040,6 @@ static HRESULT WINAPI FilterMapper2_EnumMatchingFilters( if (SUCCEEDED(hrSub)) { - V_VT(&var) = VT_ARRAY | VT_UI1; hrSub = IPropertyBag_Read(pPropBag, wszFilterDataName, &var, NULL); } @@ -1071,7 +1070,7 @@ static HRESULT WINAPI FilterMapper2_EnumMatchingFilters( const REGFILTERPINS2 * rfp2 = rf2.u.s1.rgPins2 + i; bInputMatch = bInputMatch || (!(rfp2->dwFlags & REG_PINFLAG_B_OUTPUT) && - (!bRender || (rfp2->dwFlags & REG_PINFLAG_B_RENDERER)) && + (!bRender == !(rfp2->dwFlags & REG_PINFLAG_B_RENDERER)) && MatchTypes(bExactMatch, rfp2->nMediaTypes, rfp2->lpMediaType, cInputTypes, pInputTypes)); bOutputMatch = bOutputMatch || ((rfp2->dwFlags & REG_PINFLAG_B_OUTPUT) && MatchTypes(bExactMatch, rfp2->nMediaTypes, rfp2->lpMediaType, cOutputTypes, pOutputTypes)); @@ -1273,14 +1272,14 @@ static HRESULT WINAPI FilterMapper_EnumMatchingFilters( if (SUCCEEDED(hrSub)) { - len = (strlenW((WCHAR*)&V_UNION(&var, bstrVal))+1) * sizeof(WCHAR); + len = (strlenW((WCHAR*)V_UNION(&var, bstrVal))+1) * sizeof(WCHAR); if (!(regfilters[idx].Name = CoTaskMemAlloc(len*2))) hr = E_OUTOFMEMORY; } if (SUCCEEDED(hrSub)) { - memcpy(regfilters[idx].Name, &V_UNION(&var, bstrVal), len); + memcpy(regfilters[idx].Name, V_UNION(&var, bstrVal), len); regfilters[idx].Clsid = clsid; idx++; } diff --git a/dlls/quartz/memallocator.c b/dlls/quartz/memallocator.c index 12effbb1fb9..2ee8d71cc8c 100644 --- a/dlls/quartz/memallocator.c +++ b/dlls/quartz/memallocator.c @@ -27,7 +27,6 @@ #include "vfwmsgs.h" #include "quartz_private.h" -#include "wine/list.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(quartz); @@ -51,35 +50,6 @@ void dump_AM_SAMPLE2_PROPERTIES(const AM_SAMPLE2_PROPERTIES * pProps) TRACE("\tcbBuffer: %d\n", pProps->cbBuffer); } -typedef struct BaseMemAllocator -{ - const IMemAllocatorVtbl * lpVtbl; - - LONG ref; - ALLOCATOR_PROPERTIES * pProps; - CRITICAL_SECTION csState; - HRESULT (* fnAlloc) (IMemAllocator *); - HRESULT (* fnFree)(IMemAllocator *); - HANDLE hSemWaiting; - BOOL bDecommitQueued; - BOOL bCommitted; - LONG lWaiting; - struct list free_list; - struct list used_list; -} BaseMemAllocator; - -typedef struct StdMediaSample2 -{ - const IMediaSample2Vtbl * lpvtbl; - - LONG ref; - AM_SAMPLE2_PROPERTIES props; - IMemAllocator * pParent; - struct list listentry; - LONGLONG tMediaStart; - LONGLONG tMediaEnd; -} StdMediaSample2; - static const IMemAllocatorVtbl BaseMemAllocator_VTable; static const IMediaSample2Vtbl StdMediaSample2_VTable; @@ -87,25 +57,34 @@ static const IMediaSample2Vtbl StdMediaSample2_VTable; #define INVALID_MEDIA_TIME (((ULONGLONG)0x7fffffff << 32) | 0xffffffff) -static HRESULT BaseMemAllocator_Init(HRESULT (* fnAlloc)(IMemAllocator *), HRESULT (* fnFree)(IMemAllocator *), BaseMemAllocator * pMemAlloc) +HRESULT BaseMemAllocator_Init(HRESULT (* fnAlloc)(IMemAllocator *), + HRESULT (* fnFree)(IMemAllocator *), + HRESULT (* fnVerify)(IMemAllocator *, ALLOCATOR_PROPERTIES *), + HRESULT (* fnBufferPrepare)(IMemAllocator *, StdMediaSample2 *, DWORD), + HRESULT (* fnBufferReleased)(IMemAllocator *, StdMediaSample2 *), + void (* fnDestroyed)(IMemAllocator *), + CRITICAL_SECTION *pCritSect, + BaseMemAllocator * pMemAlloc) { - assert(fnAlloc && fnFree); + assert(fnAlloc && fnFree && fnDestroyed); pMemAlloc->lpVtbl = &BaseMemAllocator_VTable; pMemAlloc->ref = 1; - pMemAlloc->pProps = NULL; + ZeroMemory(&pMemAlloc->props, sizeof(pMemAlloc->props)); list_init(&pMemAlloc->free_list); list_init(&pMemAlloc->used_list); pMemAlloc->fnAlloc = fnAlloc; pMemAlloc->fnFree = fnFree; + pMemAlloc->fnVerify = fnVerify; + pMemAlloc->fnBufferPrepare = fnBufferPrepare; + pMemAlloc->fnBufferReleased = fnBufferReleased; + pMemAlloc->fnDestroyed = fnDestroyed; pMemAlloc->bDecommitQueued = FALSE; pMemAlloc->bCommitted = FALSE; pMemAlloc->hSemWaiting = NULL; pMemAlloc->lWaiting = 0; - - InitializeCriticalSection(&pMemAlloc->csState); - pMemAlloc->csState.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BaseMemAllocator.csState"); + pMemAlloc->pCritSect = pCritSect; return S_OK; } @@ -155,10 +134,8 @@ static ULONG WINAPI BaseMemAllocator_Release(IMemAllocator * iface) CloseHandle(This->hSemWaiting); if (This->bCommitted) This->fnFree(iface); - CoTaskMemFree(This->pProps); - This->csState.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->csState); - CoTaskMemFree(This); + + This->fnDestroyed(iface); return 0; } return ref; @@ -171,7 +148,7 @@ static HRESULT WINAPI BaseMemAllocator_SetProperties(IMemAllocator * iface, ALLO TRACE("(%p)->(%p, %p)\n", This, pRequest, pActual); - EnterCriticalSection(&This->csState); + EnterCriticalSection(This->pCritSect); { if (!list_empty(&This->used_list)) hr = VFW_E_BUFFERS_OUTSTANDING; @@ -181,22 +158,18 @@ static HRESULT WINAPI BaseMemAllocator_SetProperties(IMemAllocator * iface, ALLO hr = VFW_E_BADALIGN; else { - if (!This->pProps) - This->pProps = CoTaskMemAlloc(sizeof(*This->pProps)); - - if (!This->pProps) - hr = E_OUTOFMEMORY; + if (This->fnVerify) + hr = This->fnVerify(iface, pRequest); else - { - *This->pProps = *pRequest; + hr = S_OK; - *pActual = *pRequest; + if (SUCCEEDED(hr)) + This->props = *pRequest; - hr = S_OK; - } + *pActual = This->props; } } - LeaveCriticalSection(&This->csState); + LeaveCriticalSection(This->pCritSect); return hr; } @@ -208,20 +181,11 @@ static HRESULT WINAPI BaseMemAllocator_GetProperties(IMemAllocator * iface, ALLO TRACE("(%p)->(%p)\n", This, pProps); - EnterCriticalSection(&This->csState); + EnterCriticalSection(This->pCritSect); { - /* NOTE: this is different from the native version. - * It would silently succeed if the properties had - * not been set, but would fail further on down the - * line with some obscure error like having an - * invalid alignment. Whether or not our version - * will cause any problems remains to be seen */ - if (!This->pProps) - hr = VFW_E_SIZENOTSET; - else - memcpy(pProps, This->pProps, sizeof(*pProps)); + memcpy(pProps, &This->props, sizeof(*pProps)); } - LeaveCriticalSection(&This->csState); + LeaveCriticalSection(This->pCritSect); return hr; } @@ -233,10 +197,14 @@ static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface) TRACE("(%p)->()\n", This); - EnterCriticalSection(&This->csState); + EnterCriticalSection(This->pCritSect); { - if (!This->pProps) + if (!This->props.cbAlign) + hr = VFW_E_BADALIGN; + else if (!This->props.cbBuffer) hr = VFW_E_SIZENOTSET; + else if (!This->props.cBuffers) + hr = VFW_E_BUFFER_NOTSET; else if (This->bDecommitQueued && This->bCommitted) { This->bDecommitQueued = FALSE; @@ -246,7 +214,7 @@ static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface) hr = S_OK; else { - if (!(This->hSemWaiting = CreateSemaphoreW(NULL, This->pProps->cBuffers, This->pProps->cBuffers, NULL))) + if (!(This->hSemWaiting = CreateSemaphoreW(NULL, This->props.cBuffers, This->props.cBuffers, NULL))) { ERR("Couldn't create semaphore (error was %u)\n", GetLastError()); hr = HRESULT_FROM_WIN32(GetLastError()); @@ -261,7 +229,7 @@ static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface) } } } - LeaveCriticalSection(&This->csState); + LeaveCriticalSection(This->pCritSect); return hr; } @@ -273,7 +241,7 @@ static HRESULT WINAPI BaseMemAllocator_Decommit(IMemAllocator * iface) TRACE("(%p)->()\n", This); - EnterCriticalSection(&This->csState); + EnterCriticalSection(This->pCritSect); { if (!This->bCommitted) hr = S_OK; @@ -289,7 +257,8 @@ static HRESULT WINAPI BaseMemAllocator_Decommit(IMemAllocator * iface) } else { - assert(This->lWaiting == 0); + if (This->lWaiting != 0) + ERR("Waiting: %d\n", This->lWaiting); This->bCommitted = FALSE; CloseHandle(This->hSemWaiting); @@ -301,7 +270,7 @@ static HRESULT WINAPI BaseMemAllocator_Decommit(IMemAllocator * iface) } } } - LeaveCriticalSection(&This->csState); + LeaveCriticalSection(This->pCritSect); return hr; } @@ -318,19 +287,30 @@ static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSa *pSample = NULL; - if (!This->bCommitted) - return VFW_E_NOT_COMMITTED; + EnterCriticalSection(This->pCritSect); + if (!This->bCommitted || This->bDecommitQueued) + { + WARN("Not committed\n"); + hr = VFW_E_NOT_COMMITTED; + } + else + ++This->lWaiting; + LeaveCriticalSection(This->pCritSect); + if (FAILED(hr)) + return hr; - This->lWaiting++; if (WaitForSingleObject(This->hSemWaiting, (dwFlags & AM_GBF_NOWAIT) ? 0 : INFINITE) != WAIT_OBJECT_0) { - This->lWaiting--; + EnterCriticalSection(This->pCritSect); + --This->lWaiting; + LeaveCriticalSection(This->pCritSect); + WARN("Timed out\n"); return VFW_E_TIMEOUT; } - This->lWaiting--; - EnterCriticalSection(&This->csState); + EnterCriticalSection(This->pCritSect); { + --This->lWaiting; if (!This->bCommitted) hr = VFW_E_NOT_COMMITTED; else if (This->bDecommitQueued) @@ -348,8 +328,10 @@ static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSa IMediaSample_AddRef(*pSample); } } - LeaveCriticalSection(&This->csState); + LeaveCriticalSection(This->pCritSect); + if (hr != S_OK) + WARN("%08x\n", hr); return hr; } @@ -365,7 +347,7 @@ static HRESULT WINAPI BaseMemAllocator_ReleaseBuffer(IMemAllocator * iface, IMed /* FIXME: we should probably check the ref count on the sample before freeing * it to make sure that it is not still in use */ - EnterCriticalSection(&This->csState); + EnterCriticalSection(This->pCritSect); { if (!This->bCommitted) ERR("Releasing a buffer when the allocator is not committed?!?\n"); @@ -379,7 +361,8 @@ static HRESULT WINAPI BaseMemAllocator_ReleaseBuffer(IMemAllocator * iface, IMed { HRESULT hrfree; - assert(This->lWaiting == 0); + if (This->lWaiting != 0) + ERR("Waiting: %d\n", This->lWaiting); This->bCommitted = FALSE; This->bDecommitQueued = FALSE; @@ -391,7 +374,7 @@ static HRESULT WINAPI BaseMemAllocator_ReleaseBuffer(IMemAllocator * iface, IMed ERR("fnFree failed with error 0x%x\n", hrfree); } } - LeaveCriticalSection(&This->csState); + LeaveCriticalSection(This->pCritSect); /* notify a waiting thread that there is now a free buffer */ if (This->hSemWaiting && !ReleaseSemaphore(This->hSemWaiting, 1, NULL)) @@ -416,7 +399,7 @@ static const IMemAllocatorVtbl BaseMemAllocator_VTable = BaseMemAllocator_ReleaseBuffer }; -static HRESULT StdMediaSample2_Construct(BYTE * pbBuffer, LONG cbBuffer, IMemAllocator * pParent, StdMediaSample2 ** ppSample) +HRESULT StdMediaSample2_Construct(BYTE * pbBuffer, LONG cbBuffer, IMemAllocator * pParent, StdMediaSample2 ** ppSample) { assert(pbBuffer && pParent && (cbBuffer > 0)); @@ -440,7 +423,7 @@ static HRESULT StdMediaSample2_Construct(BYTE * pbBuffer, LONG cbBuffer, IMemAll return S_OK; } -static void StdMediaSample2_Delete(StdMediaSample2 * This) +void StdMediaSample2_Delete(StdMediaSample2 * This) { /* NOTE: does not remove itself from the list it belongs to */ CoTaskMemFree(This); @@ -507,6 +490,12 @@ static HRESULT WINAPI StdMediaSample2_GetPointer(IMediaSample2 * iface, BYTE ** *ppBuffer = This->props.pbBuffer; + if (!*ppBuffer) + { + ERR("Requested an unlocked surface and trying to lock regardless\n"); + return E_FAIL; + } + return S_OK; } @@ -633,7 +622,10 @@ static HRESULT WINAPI StdMediaSample2_SetActualDataLength(IMediaSample2 * iface, TRACE("(%d)\n", len); if ((len > This->props.cbBuffer) || (len < 0)) + { + WARN("Tried to set length to %d, while max is %d\n", len, This->props.cbBuffer); return VFW_E_BUFFER_OVERFLOW; + } else { This->props.lActual = len; @@ -782,6 +774,7 @@ static const IMediaSample2Vtbl StdMediaSample2_VTable = typedef struct StdMemAllocator { BaseMemAllocator base; + CRITICAL_SECTION csState; LPVOID pMemory; } StdMemAllocator; @@ -798,21 +791,21 @@ static HRESULT StdMemAllocator_Alloc(IMemAllocator * iface) GetSystemInfo(&si); /* we do not allow a courser alignment than the OS page size */ - if ((si.dwPageSize % This->base.pProps->cbAlign) != 0) + if ((si.dwPageSize % This->base.props.cbAlign) != 0) return VFW_E_BADALIGN; /* FIXME: each sample has to have its buffer start on the right alignment. * We don't do this at the moment */ /* allocate memory */ - This->pMemory = VirtualAlloc(NULL, (This->base.pProps->cbBuffer + This->base.pProps->cbPrefix) * This->base.pProps->cBuffers, MEM_COMMIT, PAGE_READWRITE); + This->pMemory = VirtualAlloc(NULL, (This->base.props.cbBuffer + This->base.props.cbPrefix) * This->base.props.cBuffers, MEM_COMMIT, PAGE_READWRITE); - for (i = This->base.pProps->cBuffers - 1; i >= 0; i--) + for (i = This->base.props.cBuffers - 1; i >= 0; i--) { /* pbBuffer does not start at the base address, it starts at base + cbPrefix */ - BYTE * pbBuffer = (BYTE *)This->pMemory + i * (This->base.pProps->cbBuffer + This->base.pProps->cbPrefix) + This->base.pProps->cbPrefix; + BYTE * pbBuffer = (BYTE *)This->pMemory + i * (This->base.props.cbBuffer + This->base.props.cbPrefix) + This->base.props.cbPrefix; - StdMediaSample2_Construct(pbBuffer, This->base.pProps->cbBuffer, iface, &pSample); + StdMediaSample2_Construct(pbBuffer, This->base.props.cbBuffer, iface, &pSample); list_add_head(&This->base.free_list, &pSample->listentry); } @@ -853,6 +846,16 @@ static HRESULT StdMemAllocator_Free(IMemAllocator * iface) return S_OK; } +static void StdMemAllocator_Destroy(IMemAllocator *iface) +{ + StdMemAllocator *This = (StdMemAllocator *)iface; + + This->csState.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->csState); + + CoTaskMemFree(This); +} + HRESULT StdMemAllocator_create(LPUNKNOWN lpUnkOuter, LPVOID * ppv) { StdMemAllocator * pMemAlloc; @@ -866,9 +869,12 @@ HRESULT StdMemAllocator_create(LPUNKNOWN lpUnkOuter, LPVOID * ppv) if (!(pMemAlloc = CoTaskMemAlloc(sizeof(*pMemAlloc)))) return E_OUTOFMEMORY; + InitializeCriticalSection(&pMemAlloc->csState); + pMemAlloc->csState.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": StdMemAllocator.csState"); + pMemAlloc->pMemory = NULL; - if (SUCCEEDED(hr = BaseMemAllocator_Init(StdMemAllocator_Alloc, StdMemAllocator_Free, &pMemAlloc->base))) + if (SUCCEEDED(hr = BaseMemAllocator_Init(StdMemAllocator_Alloc, StdMemAllocator_Free, NULL, NULL, NULL, StdMemAllocator_Destroy, &pMemAlloc->csState, &pMemAlloc->base))) *ppv = (LPVOID)pMemAlloc; else CoTaskMemFree(pMemAlloc); diff --git a/dlls/quartz/nullrenderer.c b/dlls/quartz/nullrenderer.c index 45315f77be9..6071a4af523 100644 --- a/dlls/quartz/nullrenderer.c +++ b/dlls/quartz/nullrenderer.c @@ -198,7 +198,7 @@ HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) piInput.pFilter = (IBaseFilter *)pNullRenderer; lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); - hr = InputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_Sample, (LPVOID)pNullRenderer, NullRenderer_QueryAccept, NULL, &pNullRenderer->csFilter, (IPin **)&pNullRenderer->pInputPin); + hr = InputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_Sample, (LPVOID)pNullRenderer, NullRenderer_QueryAccept, NULL, &pNullRenderer->csFilter, NULL, (IPin **)&pNullRenderer->pInputPin); if (SUCCEEDED(hr)) { @@ -568,16 +568,21 @@ static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface) { InputPin* This = (InputPin*)iface; IMediaEventSink* pEventSink; - HRESULT hr; + IFilterGraph *graph; + HRESULT hr = S_OK; TRACE("(%p/%p)->()\n", This, iface); InputPin_EndOfStream(iface); - hr = IFilterGraph_QueryInterface(((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); - if (SUCCEEDED(hr)) + graph = ((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph; + if (graph) { - hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0); - IMediaEventSink_Release(pEventSink); + hr = IFilterGraph_QueryInterface(((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); + if (SUCCEEDED(hr)) + { + hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0); + IMediaEventSink_Release(pEventSink); + } } return hr; diff --git a/dlls/quartz/parser.c b/dlls/quartz/parser.c index 33e3d0456ad..97be991d830 100644 --- a/dlls/quartz/parser.c +++ b/dlls/quartz/parser.c @@ -217,7 +217,6 @@ HRESULT WINAPI Parser_GetClassID(IBaseFilter * iface, CLSID * pClsid) HRESULT WINAPI Parser_Stop(IBaseFilter * iface) { - HRESULT hr; ParserImpl *This = (ParserImpl *)iface; PullPin *pin = (PullPin *)This->ppPins[0]; @@ -226,19 +225,11 @@ HRESULT WINAPI Parser_Stop(IBaseFilter * iface) EnterCriticalSection(&pin->thread_lock); EnterCriticalSection(&This->csFilter); { - if (This->state == State_Stopped) - { - LeaveCriticalSection(&This->csFilter); - LeaveCriticalSection(&pin->thread_lock); - return S_OK; - } This->state = State_Stopped; } LeaveCriticalSection(&This->csFilter); - - hr = PullPin_StopProcessing(This->pInputPin); LeaveCriticalSection(&pin->thread_lock); - return hr; + return S_OK; } HRESULT WINAPI Parser_Pause(IBaseFilter * iface) @@ -300,16 +291,9 @@ HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart) if (SUCCEEDED(hr) && (This->state == State_Stopped)) { - LeaveCriticalSection(&This->csFilter); - hr = PullPin_InitProcessing(This->pInputPin); - EnterCriticalSection(&This->csFilter); - - if (SUCCEEDED(hr)) - { - for (i = 1; i < (This->cStreams + 1); i++) - { - OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]); - } + for (i = 1; i < (This->cStreams + 1); i++) + { + OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]); } } @@ -714,7 +698,6 @@ static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface) { if (This->pin.pConnectedTo) { - PullPin *ppin = (PullPin *)This; FILTER_STATE state; ParserImpl *Parser = (ParserImpl *)This->pin.pinInfo.pFilter; @@ -724,11 +707,9 @@ static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface) if (SUCCEEDED(hr) && (state == State_Stopped) && SUCCEEDED(Parser->fnDisconnect(Parser))) { - IPin_Release(This->pin.pConnectedTo); - This->pin.pConnectedTo = NULL; - - if (FAILED(hr = IMemAllocator_Decommit(ppin->pAlloc))) - ERR("Allocator decommit failed with error %x. Possible memory leak\n", hr); + LeaveCriticalSection(This->pin.pCritSec); + PullPin_Disconnect(iface); + EnterCriticalSection(This->pin.pCritSec); hr = Parser_RemoveOutputPins((ParserImpl *)This->pin.pinInfo.pFilter); } else diff --git a/dlls/quartz/pin.c b/dlls/quartz/pin.c index 8619776b497..5bce9bb299b 100644 --- a/dlls/quartz/pin.c +++ b/dlls/quartz/pin.c @@ -236,7 +236,7 @@ static HRESULT OutputPin_ConnectSpecific(IPin * iface, IPin * pReceivePin, const } static HRESULT InputPin_Init(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, - QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, InputPin * pPinImpl) + QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, InputPin * pPinImpl) { TRACE("\n"); @@ -252,7 +252,9 @@ static HRESULT InputPin_Init(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPi /* Input pin attributes */ pPinImpl->fnSampleProc = pSampleProc; pPinImpl->fnCleanProc = pCleanUp; - pPinImpl->pAllocator = NULL; + pPinImpl->pAllocator = pPinImpl->preferred_allocator = allocator; + if (pPinImpl->preferred_allocator) + IMemAllocator_AddRef(pPinImpl->preferred_allocator); pPinImpl->tStart = 0; pPinImpl->tStop = 0; pPinImpl->dRate = 1.0; @@ -299,7 +301,7 @@ static HRESULT OutputPin_Init(const IPinVtbl *OutputPin_Vtbl, const PIN_INFO * p return S_OK; } -HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IPin ** ppPin) +HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, IPin ** ppPin) { InputPin * pPinImpl; @@ -316,7 +318,7 @@ HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinI if (!pPinImpl) return E_OUTOFMEMORY; - if (SUCCEEDED(InputPin_Init(InputPin_Vtbl, pPinInfo, pSampleProc, pUserData, pQueryAccept, pCleanUp, pCritSec, pPinImpl))) + if (SUCCEEDED(InputPin_Init(InputPin_Vtbl, pPinInfo, pSampleProc, pUserData, pQueryAccept, pCleanUp, pCritSec, allocator, pPinImpl))) { *ppPin = (IPin *)pPinImpl; return S_OK; @@ -406,7 +408,10 @@ HRESULT WINAPI IPinImpl_ConnectedTo(IPin * iface, IPin ** ppPin) hr = S_OK; } else + { hr = VFW_E_NOT_CONNECTED; + *ppPin = NULL; + } } LeaveCriticalSection(This->pCritSec); @@ -552,6 +557,8 @@ ULONG WINAPI InputPin_Release(IPin * iface) FreeMediaType(&This->pin.mtCurrent); if (This->pAllocator) IMemAllocator_Release(This->pAllocator); + This->pAllocator = NULL; + This->pin.lpVtbl = NULL; CoTaskMemFree(This); return 0; } @@ -766,6 +773,9 @@ HRESULT WINAPI MemInputPin_NotifyAllocator(IMemInputPin * iface, IMemAllocator * return E_POINTER; } + if (This->preferred_allocator && pAllocator != This->preferred_allocator) + return E_FAIL; + if (This->pAllocator) IMemAllocator_Release(This->pAllocator); This->pAllocator = pAllocator; @@ -824,9 +834,7 @@ HRESULT WINAPI MemInputPin_ReceiveCanBlock(IMemInputPin * iface) { InputPin *This = impl_from_IMemInputPin(iface); - FIXME("(%p/%p)->()\n", This, iface); - - /* FIXME: we should check whether any output pins will block */ + TRACE("(%p/%p)->()\n", This, iface); return S_OK; } @@ -1269,6 +1277,8 @@ HRESULT PullPin_Construct(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInf return E_FAIL; } +static HRESULT PullPin_InitProcessing(PullPin * This); + HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) { PIN_DIRECTION pindirReceive; @@ -1279,6 +1289,7 @@ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const dump_AM_MEDIA_TYPE(pmt); EnterCriticalSection(This->pin.pCritSec); + if (!This->pin.pConnectedTo) { ALLOCATOR_PROPERTIES props; @@ -1287,9 +1298,6 @@ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const props.cbAlign = 1; props.cbPrefix = 0; - if (This->pin.pConnectedTo) - hr = VFW_E_ALREADY_CONNECTED; - if (SUCCEEDED(hr) && (This->pin.fnQueryAccept(This->pin.pUserData, pmt) != S_OK)) hr = VFW_E_TYPE_NOT_ACCEPTED; /* FIXME: shouldn't we just map common errors onto * VFW_E_TYPE_NOT_ACCEPTED and pass the value on otherwise? */ @@ -1328,9 +1336,11 @@ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const This->pin.pConnectedTo = pReceivePin; IPin_AddRef(pReceivePin); hr = IMemAllocator_Commit(This->pAlloc); - } + if (SUCCEEDED(hr)) + hr = PullPin_InitProcessing(This); + if (FAILED(hr)) { if (This->pReader) @@ -1341,6 +1351,8 @@ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const This->pAlloc = NULL; } } + else + hr = VFW_E_ALREADY_CONNECTED; LeaveCriticalSection(This->pin.pCritSec); return hr; } @@ -1399,44 +1411,6 @@ ULONG WINAPI PullPin_Release(IPin *iface) return refCount; } -static HRESULT PullPin_Standard_Request(PullPin *This, BOOL start) -{ - REFERENCE_TIME rtSampleStart; - REFERENCE_TIME rtSampleStop; - IMediaSample *sample = NULL; - HRESULT hr; - - TRACE("Requesting sample!\n"); - - if (start) - This->rtNext = This->rtCurrent; - - if (This->rtNext >= This->rtStop) - /* Last sample has already been queued, request nothing more */ - return S_OK; - - hr = IMemAllocator_GetBuffer(This->pAlloc, &sample, NULL, NULL, 0); - - if (SUCCEEDED(hr)) - { - rtSampleStart = This->rtNext; - rtSampleStop = rtSampleStart + MEDIATIME_FROM_BYTES(IMediaSample_GetSize(sample)); - if (rtSampleStop > This->rtStop) - rtSampleStop = MEDIATIME_FROM_BYTES(ALIGNUP(BYTES_FROM_MEDIATIME(This->rtStop), This->cbAlign)); - hr = IMediaSample_SetTime(sample, &rtSampleStart, &rtSampleStop); - - This->rtCurrent = This->rtNext; - This->rtNext = rtSampleStop; - - if (SUCCEEDED(hr)) - hr = IAsyncReader_Request(This->pReader, sample, 0); - } - if (FAILED(hr)) - FIXME("Failed to queue sample : %08x\n", hr); - - return hr; -} - static void CALLBACK PullPin_Flush(PullPin *This) { IMediaSample *pSample; @@ -1457,8 +1431,6 @@ static void CALLBACK PullPin_Flush(PullPin *This) break; assert(!IMediaSample_GetActualDataLength(pSample)); - if (This->fnCustomRequest) - This->fnSampleProc(This->pin.pUserData, pSample, dwUser); IMediaSample_Release(pSample); } @@ -1468,7 +1440,7 @@ static void CALLBACK PullPin_Flush(PullPin *This) LeaveCriticalSection(This->pin.pCritSec); } -static void CALLBACK PullPin_Thread_Process(PullPin *This) +static void CALLBACK PullPin_Thread_Process(PullPin *This, BOOL pause) { HRESULT hr; IMediaSample * pSample = NULL; @@ -1490,18 +1462,19 @@ static void CALLBACK PullPin_Thread_Process(PullPin *This) } /* There is no sample in our buffer */ - if (!This->fnCustomRequest) - hr = PullPin_Standard_Request(This, TRUE); - else - hr = This->fnCustomRequest(This->pin.pUserData); + hr = This->fnCustomRequest(This->pin.pUserData); if (FAILED(hr)) ERR("Request error: %x\n", hr); - EnterCriticalSection(This->pin.pCritSec); - SetEvent(This->hEventStateChanged); - LeaveCriticalSection(This->pin.pCritSec); + if (!pause) + { + EnterCriticalSection(This->pin.pCritSec); + SetEvent(This->hEventStateChanged); + LeaveCriticalSection(This->pin.pCritSec); + } + if (SUCCEEDED(hr)) do { DWORD_PTR dwUser; @@ -1510,41 +1483,10 @@ static void CALLBACK PullPin_Thread_Process(PullPin *This) hr = IAsyncReader_WaitForNext(This->pReader, 10000, &pSample, &dwUser); - /* Calling fnCustomRequest is not specifically useful here: It can be handled inside fnSampleProc */ - if (pSample && !This->fnCustomRequest) - hr = PullPin_Standard_Request(This, FALSE); - /* Return an empty sample on error to the implementation in case it does custom parsing, so it knows it's gone */ - if (SUCCEEDED(hr) || (This->fnCustomRequest && pSample)) + if (SUCCEEDED(hr)) { - REFERENCE_TIME rtStart, rtStop; - BOOL rejected; - - IMediaSample_GetTime(pSample, &rtStart, &rtStop); - - do - { - hr = This->fnSampleProc(This->pin.pUserData, pSample, dwUser); - - if (This->fnCustomRequest) - break; - - rejected = FALSE; - if (This->rtCurrent == rtStart) - { - rejected = TRUE; - TRACE("DENIED!\n"); - Sleep(10); - /* Maybe it's transient? */ - } - /* rtNext = rtCurrent, because the next sample is already queued */ - else if (rtStop != This->rtCurrent && rtStop < This->rtStop) - { - WARN("Position changed! rtStop: %u, rtCurrent: %u\n", (DWORD)BYTES_FROM_MEDIATIME(rtStop), (DWORD)BYTES_FROM_MEDIATIME(This->rtCurrent)); - PullPin_Flush(This); - hr = PullPin_Standard_Request(This, TRUE); - } - } while (rejected && (This->rtCurrent < This->rtStop && hr == S_OK && !This->stop_playback)); + hr = This->fnSampleProc(This->pin.pUserData, pSample, dwUser); } else { @@ -1572,21 +1514,17 @@ static void CALLBACK PullPin_Thread_Process(PullPin *This) if (This->fnDone) This->fnDone(This->pin.pUserData); - PullPin_Flush(This); - TRACE("End: %08x, %d\n", hr, This->stop_playback); -} - -static void CALLBACK PullPin_Thread_Pause(PullPin *This) -{ - TRACE("(%p)->()\n", This); - - EnterCriticalSection(This->pin.pCritSec); + if (pause) { + EnterCriticalSection(This->pin.pCritSec); This->state = Req_Sleepy; SetEvent(This->hEventStateChanged); + LeaveCriticalSection(This->pin.pCritSec); } - LeaveCriticalSection(This->pin.pCritSec); + + + TRACE("End: %08x, %d\n", hr, This->stop_playback); } static void CALLBACK PullPin_Thread_Stop(PullPin *This) @@ -1612,6 +1550,8 @@ static DWORD WINAPI PullPin_Thread_Main(LPVOID pv) PullPin *This = pv; CoInitializeEx(NULL, COINIT_MULTITHREADED); + PullPin_Flush(This); + for (;;) { WaitForSingleObject(This->thread_sleepy, INFINITE); @@ -1621,15 +1561,15 @@ static DWORD WINAPI PullPin_Thread_Main(LPVOID pv) switch (This->state) { case Req_Die: PullPin_Thread_Stop(This); break; - case Req_Run: PullPin_Thread_Process(This); break; - case Req_Pause: PullPin_Thread_Pause(This); break; + case Req_Run: PullPin_Thread_Process(This, FALSE); break; + case Req_Pause: PullPin_Thread_Process(This, TRUE); break; case Req_Sleepy: ERR("Should not be signalled with SLEEPY!\n"); break; default: ERR("Unknown state request: %d\n", This->state); break; } } } -HRESULT PullPin_InitProcessing(PullPin * This) +static HRESULT PullPin_InitProcessing(PullPin * This) { HRESULT hr = S_OK; @@ -1708,8 +1648,6 @@ HRESULT PullPin_PauseProcessing(PullPin * This) PullPin_WaitForStateChange(This, INFINITE); EnterCriticalSection(This->pin.pCritSec); - /* Faster! */ - IAsyncReader_BeginFlush(This->pReader); assert(!This->stop_playback); assert(This->state == Req_Run|| This->state == Req_Sleepy); @@ -1726,7 +1664,7 @@ HRESULT PullPin_PauseProcessing(PullPin * This) return S_OK; } -HRESULT PullPin_StopProcessing(PullPin * This) +static HRESULT PullPin_StopProcessing(PullPin * This) { TRACE("(%p)->()\n", This); @@ -1832,6 +1770,7 @@ HRESULT WINAPI PullPin_Disconnect(IPin *iface) { IPin_Release(This->pin.pConnectedTo); This->pin.pConnectedTo = NULL; + PullPin_StopProcessing(This); hr = S_OK; } else diff --git a/dlls/quartz/pin.h b/dlls/quartz/pin.h index 8f160bf44c3..b67ff1bb037 100644 --- a/dlls/quartz/pin.h +++ b/dlls/quartz/pin.h @@ -93,6 +93,7 @@ typedef struct InputPin REFERENCE_TIME tStop; double dRate; BOOL flushing, end_of_stream; + IMemAllocator *preferred_allocator; } InputPin; typedef struct OutputPin @@ -142,7 +143,7 @@ typedef struct PullPin #define Req_Pause 3 /*** Constructors ***/ -HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IPin ** ppPin); +HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *, IPin ** ppPin); HRESULT OutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, long outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin); HRESULT PullPin_Construct(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, STOPPROCESSPROC, REQUESTPROC pCustomRequest, LPCRITICAL_SECTION pCritSec, IPin ** ppPin); @@ -203,6 +204,7 @@ HRESULT WINAPI MemInputPin_ReceiveCanBlock(IMemInputPin * iface); /* Pull Pin */ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); +HRESULT WINAPI PullPin_Disconnect(IPin * iface); HRESULT WINAPI PullPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv); ULONG WINAPI PullPin_Release(IPin * iface); HRESULT WINAPI PullPin_EndOfStream(IPin * iface); @@ -211,8 +213,6 @@ HRESULT WINAPI PullPin_EndFlush(IPin * iface); HRESULT WINAPI PullPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); /* Thread interaction functions: Hold the thread_lock before calling them */ -HRESULT PullPin_InitProcessing(PullPin * This); HRESULT PullPin_StartProcessing(PullPin * This); -HRESULT PullPin_StopProcessing(PullPin * This); HRESULT PullPin_PauseProcessing(PullPin * This); HRESULT PullPin_WaitForStateChange(PullPin * This, DWORD dwMilliseconds); diff --git a/dlls/quartz/quartz_private.h b/dlls/quartz/quartz_private.h index 9eb1630d0e5..e025078b9ab 100644 --- a/dlls/quartz/quartz_private.h +++ b/dlls/quartz/quartz_private.h @@ -33,6 +33,7 @@ #include "wingdi.h" #include "winuser.h" #include "dshow.h" +#include "wine/list.h" #define MEDIATIME_FROM_BYTES(x) ((LONGLONG)(x) * 10000000) #define SEC_FROM_MEDIATIME(time) ((time) / 10000000) @@ -84,4 +85,49 @@ BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, B void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt); HRESULT updatehres( HRESULT original, HRESULT new ); +typedef struct StdMediaSample2 +{ + const IMediaSample2Vtbl * lpvtbl; + + LONG ref; + AM_SAMPLE2_PROPERTIES props; + IMemAllocator * pParent; + struct list listentry; + LONGLONG tMediaStart; + LONGLONG tMediaEnd; +} StdMediaSample2; + +typedef struct BaseMemAllocator +{ + const IMemAllocatorVtbl * lpVtbl; + + LONG ref; + ALLOCATOR_PROPERTIES props; + HRESULT (* fnAlloc) (IMemAllocator *); + HRESULT (* fnFree)(IMemAllocator *); + HRESULT (* fnVerify)(IMemAllocator *, ALLOCATOR_PROPERTIES *); + HRESULT (* fnBufferPrepare)(IMemAllocator *, StdMediaSample2 *, DWORD flags); + HRESULT (* fnBufferReleased)(IMemAllocator *, StdMediaSample2 *); + void (* fnDestroyed)(IMemAllocator *); + HANDLE hSemWaiting; + BOOL bDecommitQueued; + BOOL bCommitted; + LONG lWaiting; + struct list free_list; + struct list used_list; + CRITICAL_SECTION *pCritSect; +} BaseMemAllocator; + +HRESULT BaseMemAllocator_Init(HRESULT (* fnAlloc)(IMemAllocator *), + HRESULT (* fnFree)(IMemAllocator *), + HRESULT (* fnVerify)(IMemAllocator *, ALLOCATOR_PROPERTIES *), + HRESULT (* fnBufferPrepare)(IMemAllocator *, StdMediaSample2 *, DWORD), + HRESULT (* fnBufferReleased)(IMemAllocator *, StdMediaSample2 *), + void (* fnDestroyed)(IMemAllocator *), + CRITICAL_SECTION *pCritSect, + BaseMemAllocator * pMemAlloc); + +HRESULT StdMediaSample2_Construct(BYTE * pbBuffer, LONG cbBuffer, IMemAllocator * pParent, StdMediaSample2 ** ppSample); +void StdMediaSample2_Delete(StdMediaSample2 * This); + #endif /* __QUARTZ_PRIVATE_INCLUDED__ */ diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c index 3fa752294b3..967abd4ff96 100644 --- a/dlls/quartz/tests/videorenderer.c +++ b/dlls/quartz/tests/videorenderer.c @@ -68,6 +68,8 @@ static void test_query_interface(void) RELEASE_EXPECT(pBaseFilter, 1); QI_SUCCEED(pVideoRenderer, IID_IBasicVideo, pBasicVideo); RELEASE_EXPECT(pBasicVideo, 1); + QI_SUCCEED(pVideoRenderer, IID_IMediaSeeking, pMediaSeeking); + RELEASE_EXPECT(pMediaSeeking, 1); todo_wine { QI_SUCCEED(pVideoRenderer, IID_IDirectDrawVideo, pDirectDrawVideo); RELEASE_EXPECT(pDirectDrawVideo, 1); @@ -75,8 +77,6 @@ static void test_query_interface(void) RELEASE_EXPECT(pKsPropertySet, 1); QI_SUCCEED(pVideoRenderer, IID_IMediaPosition, pMediaPosition); RELEASE_EXPECT(pMediaPosition, 1); - QI_SUCCEED(pVideoRenderer, IID_IMediaSeeking, pMediaSeeking); - RELEASE_EXPECT(pMediaSeeking, 1); QI_SUCCEED(pVideoRenderer, IID_IQualityControl, pQualityControl); RELEASE_EXPECT(pQualityControl, 1); QI_SUCCEED(pVideoRenderer, IID_IQualProp, pQualProp); diff --git a/dlls/quartz/transform.c b/dlls/quartz/transform.c index 7f50268841f..d602c694739 100644 --- a/dlls/quartz/transform.c +++ b/dlls/quartz/transform.c @@ -187,7 +187,7 @@ HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSI piOutput.pFilter = (IBaseFilter *)pTransformFilter; lstrcpynW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0])); - hr = InputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, TransformFilter_Sample, pTransformFilter, TransformFilter_Input_QueryAccept, NULL, &pTransformFilter->csFilter, &pTransformFilter->ppPins[0]); + hr = InputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, TransformFilter_Sample, pTransformFilter, TransformFilter_Input_QueryAccept, NULL, &pTransformFilter->csFilter, NULL, &pTransformFilter->ppPins[0]); if (SUCCEEDED(hr)) { diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c index 416422c76c3..bda9fdf5913 100644 --- a/dlls/quartz/videorenderer.c +++ b/dlls/quartz/videorenderer.c @@ -86,6 +86,10 @@ typedef struct VideoRendererImpl BOOL bUnkOuterValid; BOOL bAggregatable; REFERENCE_TIME rtLastStop; + MediaSeekingImpl mediaSeeking; + + /* During pause we can hold a single sample, for use in GetCurrentImage */ + IMediaSample *sample_held; } VideoRendererImpl; static LRESULT CALLBACK VideoWndProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -407,6 +411,15 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample) } #endif + if (This->state == State_Paused) + { + if (This->sample_held) + IMediaSample_Release(This->sample_held); + + This->sample_held = pSample; + IMediaSample_AddRef(pSample); + } + if (This->pClock && This->state == State_Running) { REFERENCE_TIME time, trefstart, trefstop; @@ -482,6 +495,62 @@ static HRESULT VideoRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt return S_FALSE; } +static inline VideoRendererImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) +{ + return (VideoRendererImpl *)((char*)iface - FIELD_OFFSET(VideoRendererImpl, mediaSeeking.lpVtbl)); +} + +static HRESULT WINAPI VideoRendererImpl_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv) +{ + VideoRendererImpl *This = impl_from_IMediaSeeking(iface); + + return IUnknown_QueryInterface((IUnknown *)This, riid, ppv); +} + +static ULONG WINAPI VideoRendererImpl_Seeking_AddRef(IMediaSeeking * iface) +{ + VideoRendererImpl *This = impl_from_IMediaSeeking(iface); + + return IUnknown_AddRef((IUnknown *)This); +} + +static ULONG WINAPI VideoRendererImpl_Seeking_Release(IMediaSeeking * iface) +{ + VideoRendererImpl *This = impl_from_IMediaSeeking(iface); + + return IUnknown_Release((IUnknown *)This); +} + +static const IMediaSeekingVtbl VideoRendererImpl_Seeking_Vtbl = +{ + VideoRendererImpl_Seeking_QueryInterface, + VideoRendererImpl_Seeking_AddRef, + VideoRendererImpl_Seeking_Release, + MediaSeekingImpl_GetCapabilities, + MediaSeekingImpl_CheckCapabilities, + MediaSeekingImpl_IsFormatSupported, + MediaSeekingImpl_QueryPreferredFormat, + MediaSeekingImpl_GetTimeFormat, + MediaSeekingImpl_IsUsingTimeFormat, + MediaSeekingImpl_SetTimeFormat, + MediaSeekingImpl_GetDuration, + MediaSeekingImpl_GetStopPosition, + MediaSeekingImpl_GetCurrentPosition, + MediaSeekingImpl_ConvertTimeFormat, + MediaSeekingImpl_SetPositions, + MediaSeekingImpl_GetPositions, + MediaSeekingImpl_GetAvailable, + MediaSeekingImpl_SetRate, + MediaSeekingImpl_GetRate, + MediaSeekingImpl_GetPreroll +}; + +static HRESULT VideoRendererImpl_Change(IBaseFilter *iface) +{ + TRACE("(%p)\n", iface); + return S_OK; +} + HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) { HRESULT hr; @@ -521,10 +590,14 @@ HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) piInput.pFilter = (IBaseFilter *)pVideoRenderer; lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); - hr = InputPin_Construct(&VideoRenderer_InputPin_Vtbl, &piInput, VideoRenderer_Sample, (LPVOID)pVideoRenderer, VideoRenderer_QueryAccept, NULL, &pVideoRenderer->csFilter, (IPin **)&pVideoRenderer->pInputPin); + hr = InputPin_Construct(&VideoRenderer_InputPin_Vtbl, &piInput, VideoRenderer_Sample, (LPVOID)pVideoRenderer, VideoRenderer_QueryAccept, NULL, &pVideoRenderer->csFilter, NULL, (IPin **)&pVideoRenderer->pInputPin); if (SUCCEEDED(hr)) { + MediaSeekingImpl_Init((IBaseFilter*)pVideoRenderer, VideoRendererImpl_Change, VideoRendererImpl_Change, VideoRendererImpl_Change, &pVideoRenderer->mediaSeeking, &pVideoRenderer->csFilter); + pVideoRenderer->mediaSeeking.lpVtbl = &VideoRendererImpl_Seeking_Vtbl; + + pVideoRenderer->sample_held = NULL; *ppv = (LPVOID)pVideoRenderer; } else @@ -568,6 +641,8 @@ static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown * iface, REFIID *ppv = (LPVOID)&(This->IBasicVideo_vtbl); else if (IsEqualIID(riid, &IID_IVideoWindow)) *ppv = (LPVOID)&(This->IVideoWindow_vtbl); + else if (IsEqualIID(riid, &IID_IMediaSeeking)) + *ppv = &This->mediaSeeking; if (*ppv) { @@ -712,9 +787,15 @@ static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface) EnterCriticalSection(&This->csFilter); { This->state = State_Stopped; + + if (This->sample_held) + { + IMediaSample_Release(This->sample_held); + This->sample_held = NULL; + } } LeaveCriticalSection(&This->csFilter); - + return S_OK; } @@ -750,6 +831,12 @@ static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tSta This->rtStreamStart = tStart; This->state = State_Running; + + if (This->sample_held) + { + IMediaSample_Release(This->sample_held); + This->sample_held = NULL; + } } LeaveCriticalSection(&This->csFilter); @@ -1376,8 +1463,59 @@ static HRESULT WINAPI Basicvideo_GetCurrentImage(IBasicVideo *iface, long *pBufferSize, long *pDIBImage) { ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); + BITMAPINFOHEADER *bmiHeader; + LONG needed_size; + AM_MEDIA_TYPE *amt = &This->pInputPin->pin.mtCurrent; + char *ptr; + + EnterCriticalSection(&This->csFilter); + + if (!This->sample_held) + { + LeaveCriticalSection(&This->csFilter); + return (This->state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED); + } - FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pBufferSize, pDIBImage); + FIXME("(%p/%p)->(%p, %p): partial stub\n", This, iface, pBufferSize, pDIBImage); + + if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo)) + { + bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader; + } + else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2)) + { + bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader; + } + else + { + FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype)); + LeaveCriticalSection(&This->csFilter); + return VFW_E_RUNTIME_ERROR; + } + + needed_size = bmiHeader->biSize; + needed_size += IMediaSample_GetActualDataLength(This->sample_held); + + if (!pDIBImage) + { + *pBufferSize = needed_size; + LeaveCriticalSection(&This->csFilter); + return S_OK; + } + + if (needed_size < *pBufferSize) + { + ERR("Buffer too small %u/%lu\n", needed_size, *pBufferSize); + LeaveCriticalSection(&This->csFilter); + return E_FAIL; + } + *pBufferSize = needed_size; + + memcpy(pDIBImage, bmiHeader, bmiHeader->biSize); + IMediaSample_GetPointer(This->sample_held, (BYTE **)&ptr); + memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(This->sample_held)); + + LeaveCriticalSection(&This->csFilter); return S_OK; } diff --git a/dlls/quartz/waveparser.c b/dlls/quartz/waveparser.c index 9c5e6fa920e..dbc096cdb04 100644 --- a/dlls/quartz/waveparser.c +++ b/dlls/quartz/waveparser.c @@ -381,7 +381,7 @@ static HRESULT WAVEParser_first_request(LPVOID iface) hr = IAsyncReader_Request(pin->pReader, sample, 0); } if (FAILED(hr)) - ERR("Horsemen of the apocalypse came to bring error 0x%08x\n", hr); + ERR("Horsemen of the apocalypse came to bring error 0x%08x %p\n", hr, sample); return hr; } diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c index 34513015c31..462b98a3c5f 100644 --- a/dlls/riched20/caret.c +++ b/dlls/riched20/caret.c @@ -164,7 +164,6 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, ME_DisplayItem *pCursorRun = pCursor->pRun; ME_DisplayItem *pSizeRun = pCursor->pRun; - assert(!pCursor->nOffset || !editor->bCaretAtEnd); assert(height && x && y); assert(!(ME_GetParagraph(pCursorRun)->member.para.nFlags & MEPF_REWRAP)); assert(pCursor->pRun); @@ -182,9 +181,9 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, ME_InitContext(&c, editor, hDC); - if (!pCursor->nOffset && !editor->bCaretAtEnd) + if (!pCursor->nOffset) { - ME_DisplayItem *prev = ME_FindItemBack(pCursorRun, diRunOrStartRow); + ME_DisplayItem *prev = ME_FindItemBack(pCursorRun, diRunOrParagraph); assert(prev); if (prev->type == diRun) pSizeRun = prev; @@ -209,15 +208,14 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor, row->member.row.nLMargin); } } - if (pCursor->nOffset && !(run->member.run.nFlags & MERF_SKIPPED)) { + if (pCursor->nOffset) { sz = ME_GetRunSize(&c, ¶->member.para, &run->member.run, pCursor->nOffset, row->member.row.nLMargin); } *height = pSizeRun->member.run.nAscent + pSizeRun->member.run.nDescent; *x = run->member.run.pt.x + sz.cx; - *y = para->member.para.nYPos + row->member.row.nBaseline + pSizeRun->member.run.pt.y - pSizeRun->member.run.nAscent - ME_GetYScrollPos(editor); - + *y = para->member.para.nYPos + row->member.row.nBaseline + run->member.run.pt.y - pSizeRun->member.run.nAscent - ME_GetYScrollPos(editor); ME_DestroyContext(&c, editor->hWnd); return; } @@ -238,6 +236,10 @@ ME_MoveCaret(ME_TextEditor *editor) ME_GetCursorCoordinates(editor, &editor->pCursors[0], &x, &y, &height); if(editor->bHaveFocus) { + RECT rect; + + GetClientRect(editor->hWnd, &rect); + x = min(x, rect.right-2); CreateCaret(editor->hWnd, NULL, 0, height); SetCaretPos(x, y); } @@ -967,6 +969,7 @@ void ME_MouseMove(ME_TextEditor *editor, int x, int y) ME_InvalidateSelection(editor); ShowCaret(editor->hWnd); ME_SendSelChange(editor); + SendMessageW(editor->hWnd, EM_SCROLLCARET, 0, 0); } static ME_DisplayItem *ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pRow, @@ -976,13 +979,13 @@ static ME_DisplayItem *ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pR pNext = ME_FindItemFwd(pRow, diRunOrStartRow); assert(pNext->type == diRun); pLastRun = pNext; - *pbCaretAtEnd = FALSE; + if (pbCaretAtEnd) *pbCaretAtEnd = FALSE; + if (pOffset) *pOffset = 0; do { int run_x = pNext->member.run.pt.x; int width = pNext->member.run.nWidth; if (x < run_x) { - if (pOffset) *pOffset = 0; return pNext; } if (x >= run_x && x < run_x+width) @@ -1002,12 +1005,9 @@ static ME_DisplayItem *ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pR if ((pLastRun->member.run.nFlags & MERF_ENDPARA) == 0) { pNext = ME_FindItemFwd(pNext, diRun); - if (pbCaretAtEnd) *pbCaretAtEnd = 1; - if (pOffset) *pOffset = 0; + if (pbCaretAtEnd) *pbCaretAtEnd = TRUE; return pNext; } else { - if (pbCaretAtEnd) *pbCaretAtEnd = 0; - if (pOffset) *pOffset = 0; return pLastRun; } } @@ -1179,9 +1179,6 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) static void ME_ArrowHome(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRow = ME_FindItemBack(pCursor->pRun, diStartRow); - /* bCaretAtEnd doesn't make sense if the cursor isn't set at the - first character of the next row */ - assert(!editor->bCaretAtEnd || !pCursor->nOffset); ME_WrapMarkedParagraphs(editor); if (pRow) { ME_DisplayItem *pRun; @@ -1297,19 +1294,7 @@ void ME_DeleteSelection(ME_TextEditor *editor) ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor) { - ME_Style *style; - int from, to; - - ME_GetSelection(editor, &from, &to); - if (from != to) { - ME_Cursor c; - ME_CursorFromCharOfs(editor, from, &c); - style = c.pRun->member.run.style; - ME_AddRefStyle(style); /* ME_GetInsertStyle has already done that */ - } - else - style = ME_GetInsertStyle(editor, 0); - return style; + return ME_GetInsertStyle(editor, 0); } void ME_SendSelChange(ME_TextEditor *editor) diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index 8acb74d9b14..28850f9f3d9 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -124,7 +124,7 @@ - EM_SETWORDWRAPMODE 1.0asian + EM_SETZOOM 3.0 + EM_SHOWSCROLLBAR 2.0 - - EM_STOPGROUPTYPING 2.0 + + EM_STOPGROUPTYPING 2.0 + EM_STREAMIN + EM_STREAMOUT + EM_UNDO @@ -190,7 +190,6 @@ * RICHED20 TODO (incomplete): * * - messages/styles/notifications listed above - * - Undo coalescing * - add remaining CHARFORMAT/PARAFORMAT fields * - right/center align should strip spaces from the beginning * - pictures/OLE objects (not just smiling faces that lack API support ;-) ) @@ -970,11 +969,11 @@ static void ME_RTFReadHook(RTF_Info *info) { { ME_Style *s; RTFFlushOutputBuffer(info); - if (info->stackTop<=1) { + info->stackTop--; + if (info->stackTop<=0) { info->rtfClass = rtfEOF; return; } - info->stackTop--; assert(info->stackTop >= 0); if (info->styleChanged) { @@ -1102,6 +1101,9 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre if (parser.lpRichEditOle) IRichEditOle_Release(parser.lpRichEditOle); + if (!inStream.editstream->dwError && parser.stackTop > 0) + inStream.editstream->dwError = HRESULT_FROM_WIN32(ERROR_HANDLE_EOF); + /* Remove last line break, as mandated by tests. This is not affected by CR/LF counters, since RTF streaming presents only \para tokens, which are converted according to the standard rules: \r for 2.0, \r\n for 1.0 @@ -1148,7 +1150,9 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre if (!(format & SFF_SELECTION)) { ME_ClearTempStyle(editor); } + HideCaret(editor->hWnd); ME_MoveCaret(editor); + ShowCaret(editor->hWnd); ME_SendSelChange(editor); ME_SendRequestResize(editor, FALSE); @@ -1544,6 +1548,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) case VK_END: case VK_PRIOR: case VK_NEXT: + ME_CommitUndo(editor); /* End coalesced undos for typed characters */ ME_ArrowKey(editor, nKey, shift_is_down, ctrl_is_down); return TRUE; case VK_BACK: @@ -1552,12 +1557,26 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey) if (GetWindowLongW(editor->hWnd, GWL_STYLE) & ES_READONLY) return FALSE; if (ME_IsSelection(editor)) + { ME_DeleteSelection(editor); - else if (nKey == VK_DELETE || ME_ArrowKey(editor, VK_LEFT, FALSE, FALSE)) + ME_CommitUndo(editor); + } + else if (nKey == VK_DELETE) + { + /* Delete stops group typing. + * (See MSDN remarks on EM_STOPGROUPTYPING message) */ ME_DeleteTextAtCursor(editor, 1, 1); + ME_CommitUndo(editor); + } + else if (ME_ArrowKey(editor, VK_LEFT, FALSE, FALSE)) + { + /* Backspace can be grouped for a single undo */ + ME_ContinueCoalescingTransaction(editor); + ME_DeleteTextAtCursor(editor, 1, 1); + ME_CommitCoalescingUndo(editor); + } else return TRUE; - ME_CommitUndo(editor); ME_UpdateSelectionLinkAttribute(editor); ME_UpdateRepaint(editor); ME_SendRequestResize(editor, FALSE); @@ -1664,7 +1683,6 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) { ed->mode = TM_RICHTEXT | TM_MULTILEVELUNDO | TM_MULTICODEPAGE; ed->AutoURLDetect_bEnable = FALSE; ed->bHaveFocus = FALSE; - GetClientRect(hWnd, &ed->rcFormat); for (i=0; ipFontCache[i].nRefs = 0; @@ -2046,11 +2064,9 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, return editor->pRedoStack != NULL; case WM_UNDO: /* FIXME: actually not the same */ case EM_UNDO: - ME_Undo(editor); - return 0; + return ME_Undo(editor); case EM_REDO: - ME_Redo(editor); - return 0; + return ME_Redo(editor); case EM_GETOPTIONS: { /* these flags are equivalent to the ES_* counterparts */ @@ -2617,7 +2633,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->lpUsedDefChar); + rc = WideCharToMultiByte(ex->codepage, flags, buffer, buflen+1, (LPSTR)lParam, ex->cb, ex->lpDefaultChar, ex->lpUsedDefChar); if (rc) rc--; /* do not count 0 terminator */ heap_free(buffer); @@ -2899,6 +2915,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ME_DisplayItem *pRun; int nCharOfs, nOffset, nLength; POINTL pt = {0,0}; + SCROLLINFO si; nCharOfs = wParam; /* detect which API version we're dealing with */ @@ -2917,12 +2934,21 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, pt.y = editor->pBuffer->pLast->member.para.nYPos; } pt.x += editor->selofs; + + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + if (GetScrollInfo(editor->hWnd, SB_VERT, &si)) pt.y -= si.nPos; + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + if (GetScrollInfo(editor->hWnd, SB_HORZ, &si)) pt.x -= si.nPos; + if (wParam >= 0x40000) { *(POINTL *)wParam = pt; } - return MAKELONG( pt.x, pt.y ); + return (wParam >= 0x40000) ? 0 : MAKELONG( pt.x, pt.y ); } case WM_CREATE: + GetClientRect(hWnd, &editor->rcFormat); if (GetWindowLongW(hWnd, GWL_STYLE) & WS_HSCROLL) { /* Squelch the default horizontal scrollbar it would make */ ShowScrollBar(editor->hWnd, SB_HORZ, FALSE); @@ -2936,6 +2962,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, SetWindowLongPtrW(hWnd, 0, 0); return 0; case WM_LBUTTONDOWN: + ME_CommitUndo(editor); /* End coalesced undos for typed characters */ if ((editor->nEventMask & ENM_MOUSEEVENTS) && !ME_FilterEvent(editor, msg, &wParam, &lParam)) return 0; @@ -2978,6 +3005,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, break; case WM_RBUTTONUP: case WM_RBUTTONDOWN: + ME_CommitUndo(editor); /* End coalesced undos for typed characters */ if ((editor->nEventMask & ENM_MOUSEEVENTS) && !ME_FilterEvent(editor, msg, &wParam, &lParam)) return 0; @@ -3003,6 +3031,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ME_SendOldNotify(editor, EN_SETFOCUS); return 0; case WM_KILLFOCUS: + ME_CommitUndo(editor); /* End coalesced undos for typed characters */ ME_HideCaret(editor); editor->bHaveFocus = FALSE; ME_SendOldNotify(editor, EN_KILLFOCUS); @@ -3088,12 +3117,13 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, { ME_Style *style = ME_GetInsertStyle(editor, 0); ME_SaveTempStyle(editor); + ME_ContinueCoalescingTransaction(editor); if (wstr == '\r' && (GetKeyState(VK_SHIFT) & 0x8000)) ME_InsertEndRowFromCursor(editor, 0); else ME_InsertTextFromCursor(editor, 0, &wstr, 1, style); ME_ReleaseStyle(style); - ME_CommitUndo(editor); + ME_CommitCoalescingUndo(editor); } if (editor->AutoURLDetect_bEnable) ME_UpdateSelectionLinkAttribute(editor); @@ -3102,6 +3132,9 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, } return 0; } + case EM_STOPGROUPTYPING: + ME_CommitUndo(editor); /* End coalesced undos for typed characters */ + return 0; case EM_SCROLL: /* fall through */ case WM_VSCROLL: { @@ -3879,7 +3912,7 @@ BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, int sel_min, int sel_max) return TRUE; } } - if (bufferW != NULL) heap_free(bufferW); + heap_free(bufferW); return FALSE; } diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h index 61ecf1b4098..0fc615a3f09 100644 --- a/dlls/riched20/editor.h +++ b/dlls/riched20/editor.h @@ -214,8 +214,6 @@ void ME_DestroyContext(ME_Context *c, HWND release); BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor); void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor); void ME_SendRequestResize(ME_TextEditor *editor, BOOL force); -int ME_twips2pointsX(ME_Context *c, int x); -int ME_twips2pointsY(ME_Context *c, int y); /* para.c */ ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run); @@ -244,6 +242,8 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun); void ME_InvalidateSelection(ME_TextEditor *editor); void ME_QueueInvalidateFromCursor(ME_TextEditor *editor, int nCursor); BOOL ME_SetZoom(ME_TextEditor *editor, int numerator, int denominator); +int ME_twips2pointsX(ME_Context *c, int x); +int ME_twips2pointsY(ME_Context *c, int y); /* scroll functions in paint.c */ @@ -288,8 +288,10 @@ void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor); /* undo.c */ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_DisplayItem *pdi); void ME_CommitUndo(ME_TextEditor *editor); -void ME_Undo(ME_TextEditor *editor); -void ME_Redo(ME_TextEditor *editor); +void ME_ContinueCoalescingTransaction(ME_TextEditor *editor); +void ME_CommitCoalescingUndo(ME_TextEditor *editor); +BOOL ME_Undo(ME_TextEditor *editor); +BOOL ME_Redo(ME_TextEditor *editor); void ME_EmptyUndoStack(ME_TextEditor *editor); /* writer.c */ diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index 1e2c770fbbe..d54edbf0334 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -85,8 +85,9 @@ typedef enum { diUndoSplitParagraph, /* 14 */ diUndoSetParagraphFormat, /* 15 */ diUndoSetCharFormat, /* 16 */ - diUndoEndTransaction, /* 17 */ + diUndoEndTransaction, /* 17 - marks the end of a group of changes for undo */ diUndoSetDefaultCharFormat, /* 18 */ + diUndoPotentialEndTransaction, /* 19 - allows grouping typed chars for undo */ } ME_DIType; /******************************** run flags *************************/ diff --git a/dlls/riched20/list.c b/dlls/riched20/list.c index 951e7f36e2b..f5c5f42fd8d 100644 --- a/dlls/riched20/list.c +++ b/dlls/riched20/list.c @@ -169,6 +169,7 @@ const char *ME_GetDITypeName(ME_DIType type) case diTextEnd: return "diTextEnd"; case diStartRow: return "diStartRow"; case diUndoEndTransaction: return "diUndoEndTransaction"; + case diUndoPotentialEndTransaction: return "diUndoPotentialEndTransaction"; case diUndoSetParagraphFormat: return "diUndoSetParagraphFormat"; case diUndoSetCharFormat: return "diUndoSetCharFormat"; case diUndoInsertRun: return "diUndoInsertRun"; diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c index 88576f620c4..95befbc72f0 100644 --- a/dlls/riched20/paint.c +++ b/dlls/riched20/paint.c @@ -674,14 +674,9 @@ void ME_Scroll(ME_TextEditor *editor, int value, int type) si.fMask |= SIF_DISABLENOSCROLL; si.nMin = 0; + si.nMax = editor->nTotalLength; - if (ME_GetTextLength(editor) > 0) - { - si.nMax = editor->nTotalLength; - si.nPage = editor->sizeWindow.cy; - } else { - si.nMax = si.nPage = 0; - } + si.nPage = editor->sizeWindow.cy; TRACE("min=%d max=%d page=%d\n", si.nMin, si.nMax, si.nPage); SetScrollInfo(hWnd, SB_VERT, &si, TRUE); diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c index 8380a79b425..de69794c33d 100644 --- a/dlls/riched20/para.c +++ b/dlls/riched20/para.c @@ -52,7 +52,8 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor) cf.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR; lstrcpyW(cf.szFaceName, lf.lfFaceName); - cf.yHeight = ME_twips2pointsY(&c, lf.lfHeight); + /* Convert system font height from logical units to twips for cf.yHeight */ + cf.yHeight = (lf.lfHeight * 72 * 1440) / (c.dpi.cy * c.dpi.cy); if (lf.lfWeight > FW_NORMAL) cf.dwEffects |= CFE_BOLD; cf.wWeight = lf.lfWeight; if (lf.lfItalic) cf.dwEffects |= CFE_ITALIC; @@ -104,7 +105,7 @@ void ME_MarkForWrapping(ME_TextEditor *editor, ME_DisplayItem *first, const ME_D void ME_MarkForPainting(ME_TextEditor *editor, ME_DisplayItem *first, const ME_DisplayItem *last) { - while(first != last) + while(first != last && first) { first->member.para.nFlags |= MEPF_REPAINT; first = first->member.para.next_para; diff --git a/dlls/riched20/reader.c b/dlls/riched20/reader.c index 5ee9fa27f9b..f456a09fdc3 100644 --- a/dlls/riched20/reader.c +++ b/dlls/riched20/reader.c @@ -638,14 +638,16 @@ static void _RTFGetToken2(RTF_Info *info) { int c2; - if ((c = GetChar (info)) != EOF && (c2 = GetChar (info)) != EOF) + if ((c = GetChar (info)) != EOF && (c2 = GetChar (info)) != EOF + && isxdigit(c) && isxdigit(c2)) { - /* should do isxdigit check! */ info->rtfClass = rtfText; info->rtfMajor = RTFCharToHex (c) * 16 + RTFCharToHex (c2); return; } - /* early eof, whoops (class is rtfUnknown) */ + /* early eof, whoops */ + info->rtfClass = rtfEOF; + info->stream->editstream->dwError = -14; return; } @@ -2665,10 +2667,10 @@ RTFPutUnicodeString(RTF_Info *info, const WCHAR *string, int length) memmove(info->OutputBuffer + info->dwOutputCount, string, fit * sizeof(WCHAR)); info->dwOutputCount += fit; - if (fit == sizeof(info->OutputBuffer) / sizeof(WCHAR) - info->dwOutputCount) - RTFFlushUnicodeOutputBuffer(info); length -= fit; string += fit; + if (sizeof(info->OutputBuffer) / sizeof(WCHAR) == info->dwOutputCount) + RTFFlushUnicodeOutputBuffer(info); } } diff --git a/dlls/riched20/richole.c b/dlls/riched20/richole.c index 3d5e42f26b8..9eabb04754d 100644 --- a/dlls/riched20/richole.c +++ b/dlls/riched20/richole.c @@ -48,6 +48,10 @@ TEXTSERV_GUID(IID_ITextServices, 0x8d33f740, 0xcf58, 0x11ce, 0xa8, 0x9d); TEXTSERV_GUID(IID_ITextHost, 0xc5bdd8d0, 0xd26e, 0x11ce, 0xa8, 0x9e); TEXTSERV_GUID(IID_ITextHost2, 0xc5bdd8d0, 0xd26e, 0x11ce, 0xa8, 0x9e); DEFINE_GUID(IID_ITextDocument, 0x8cc497c0, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); +DEFINE_GUID(IID_ITextRange, 0x8cc497c2, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); +DEFINE_GUID(IID_ITextSelection, 0x8cc497c1, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); + +typedef struct ITextSelectionImpl ITextSelectionImpl; typedef struct IRichEditOleImpl { const IRichEditOleVtbl *lpRichEditOleVtbl; @@ -55,8 +59,16 @@ typedef struct IRichEditOleImpl { LONG ref; ME_TextEditor *editor; + ITextSelectionImpl *txtSel; } IRichEditOleImpl; +struct ITextSelectionImpl { + const ITextSelectionVtbl *lpVtbl; + LONG ref; + + IRichEditOleImpl *reOle; +}; + static inline IRichEditOleImpl *impl_from_IRichEditOle(IRichEditOle *iface) { return (IRichEditOleImpl *)((BYTE*)iface - FIELD_OFFSET(IRichEditOleImpl, lpRichEditOleVtbl)); @@ -112,6 +124,8 @@ IRichEditOle_fnRelease(IRichEditOle *me) if (!ref) { TRACE ("Destroying %p\n", This); + This->txtSel->reOle = NULL; + ITextSelection_Release((ITextSelection *) This->txtSel); heap_free(This); } return ref; @@ -358,8 +372,10 @@ static HRESULT WINAPI ITextDocument_fnGetSelection(ITextDocument* me, ITextSelection** ppSel) { IRichEditOleImpl *This = impl_from_ITextDocument(me); - FIXME("stub %p\n",This); - return E_NOTIMPL; + TRACE("(%p)\n", me); + *ppSel = (ITextSelection *) This->txtSel; + ITextSelection_AddRef(*ppSel); + return S_OK; } static HRESULT WINAPI @@ -532,6 +548,981 @@ static const ITextDocumentVtbl tdvt = { ITextDocument_fnRangeFromPoint }; +static HRESULT WINAPI ITextSelection_fnQueryInterface( + ITextSelection *me, + REFIID riid, + void **ppvObj) +{ + *ppvObj = NULL; + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IDispatch) + || IsEqualGUID(riid, &IID_ITextRange) + || IsEqualGUID(riid, &IID_ITextSelection)) + { + *ppvObj = me; + ITextSelection_AddRef(me); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI ITextSelection_fnAddRef( + ITextSelection *me) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI ITextSelection_fnRelease( + ITextSelection *me) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + ULONG ref = InterlockedDecrement(&This->ref); + if (ref == 0) + heap_free(This); + return ref; +} + +static HRESULT WINAPI ITextSelection_fnGetTypeInfoCount( + ITextSelection *me, + UINT *pctinfo) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetTypeInfo( + ITextSelection *me, + UINT iTInfo, + LCID lcid, + ITypeInfo **ppTInfo) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetIDsOfNames( + ITextSelection *me, + REFIID riid, + LPOLESTR *rgszNames, + UINT cNames, + LCID lcid, + DISPID *rgDispId) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnInvoke( + ITextSelection *me, + DISPID dispIdMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS *pDispParams, + VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, + UINT *puArgErr) +{ + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +/*** ITextRange methods ***/ +static HRESULT WINAPI ITextSelection_fnGetText( + ITextSelection *me, + BSTR *pbstr) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSetText( + ITextSelection *me, + BSTR bstr) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetChar( + ITextSelection *me, + long *pch) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSetChar( + ITextSelection *me, + long ch) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetDuplicate( + ITextSelection *me, + ITextRange **ppRange) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetFormattedText( + ITextSelection *me, + ITextRange **ppRange) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSetFormattedText( + ITextSelection *me, + ITextRange *pRange) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetStart( + ITextSelection *me, + long *pcpFirst) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSetStart( + ITextSelection *me, + long cpFirst) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetEnd( + ITextSelection *me, + long *pcpLim) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSetEnd( + ITextSelection *me, + long cpLim) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetFont( + ITextSelection *me, + ITextFont **pFont) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSetFont( + ITextSelection *me, + ITextFont *pFont) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetPara( + ITextSelection *me, + ITextPara **ppPara) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSetPara( + ITextSelection *me, + ITextPara *pPara) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetStoryLength( + ITextSelection *me, + long *pcch) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetStoryType( + ITextSelection *me, + long *pValue) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnCollapse( + ITextSelection *me, + long bStart) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnExpand( + ITextSelection *me, + long Unit, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetIndex( + ITextSelection *me, + long Unit, + long *pIndex) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSetIndex( + ITextSelection *me, + long Unit, + long Index, + long Extend) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSetRange( + ITextSelection *me, + long cpActive, + long cpOther) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnInRange( + ITextSelection *me, + ITextRange *pRange, + long *pb) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnInStory( + ITextSelection *me, + ITextRange *pRange, + long *pb) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnIsEqual( + ITextSelection *me, + ITextRange *pRange, + long *pb) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSelect( + ITextSelection *me) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnStartOf( + ITextSelection *me, + long Unit, + long Extend, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnEndOf( + ITextSelection *me, + long Unit, + long Extend, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMove( + ITextSelection *me, + long Unit, + long Count, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveStart( + ITextSelection *me, + long Unit, + long Count, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveEnd( + ITextSelection *me, + long Unit, + long Count, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveWhile( + ITextSelection *me, + VARIANT *Cset, + long Count, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveStartWhile( + ITextSelection *me, + VARIANT *Cset, + long Count, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveEndWhile( + ITextSelection *me, + VARIANT *Cset, + long Count, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveUntil( + ITextSelection *me, + VARIANT *Cset, + long Count, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveStartUntil( + ITextSelection *me, + VARIANT *Cset, + long Count, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveEndUntil( + ITextSelection *me, + VARIANT *Cset, + long Count, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnFindText( + ITextSelection *me, + BSTR bstr, + long cch, + long Flags, + long *pLength) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnFindTextStart( + ITextSelection *me, + BSTR bstr, + long cch, + long Flags, + long *pLength) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnFindTextEnd( + ITextSelection *me, + BSTR bstr, + long cch, + long Flags, + long *pLength) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnDelete( + ITextSelection *me, + long Unit, + long Count, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnCut( + ITextSelection *me, + VARIANT *pVar) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnCopy( + ITextSelection *me, + VARIANT *pVar) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnPaste( + ITextSelection *me, + VARIANT *pVar, + long Format) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnCanPaste( + ITextSelection *me, + VARIANT *pVar, + long Format, + long *pb) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnCanEdit( + ITextSelection *me, + long *pb) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnChangeCase( + ITextSelection *me, + long Type) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetPoint( + ITextSelection *me, + long Type, + long *cx, + long *cy) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSetPoint( + ITextSelection *me, + long x, + long y, + long Type, + long Extend) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnScrollIntoView( + ITextSelection *me, + long Value) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetEmbeddedObject( + ITextSelection *me, + IUnknown **ppv) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +/*** ITextSelection methods ***/ +static HRESULT WINAPI ITextSelection_fnGetFlags( + ITextSelection *me, + long *pFlags) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnSetFlags( + ITextSelection *me, + long Flags) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnGetType( + ITextSelection *me, + long *pType) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveLeft( + ITextSelection *me, + long Unit, + long Count, + long Extend, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveRight( + ITextSelection *me, + long Unit, + long Count, + long Extend, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveUp( + ITextSelection *me, + long Unit, + long Count, + long Extend, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnMoveDown( + ITextSelection *me, + long Unit, + long Count, + long Extend, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnHomeKey( + ITextSelection *me, + long Unit, + long Extend, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnEndKey( + ITextSelection *me, + long Unit, + long Extend, + long *pDelta) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI ITextSelection_fnTypeText( + ITextSelection *me, + BSTR bstr) +{ + ITextSelectionImpl *This = (ITextSelectionImpl *) me; + if (!This->reOle) + return CO_E_RELEASED; + + FIXME("not implemented\n"); + return E_NOTIMPL; +} + +static const ITextSelectionVtbl tsvt = { + ITextSelection_fnQueryInterface, + ITextSelection_fnAddRef, + ITextSelection_fnRelease, + ITextSelection_fnGetTypeInfoCount, + ITextSelection_fnGetTypeInfo, + ITextSelection_fnGetIDsOfNames, + ITextSelection_fnInvoke, + ITextSelection_fnGetText, + ITextSelection_fnSetText, + ITextSelection_fnGetChar, + ITextSelection_fnSetChar, + ITextSelection_fnGetDuplicate, + ITextSelection_fnGetFormattedText, + ITextSelection_fnSetFormattedText, + ITextSelection_fnGetStart, + ITextSelection_fnSetStart, + ITextSelection_fnGetEnd, + ITextSelection_fnSetEnd, + ITextSelection_fnGetFont, + ITextSelection_fnSetFont, + ITextSelection_fnGetPara, + ITextSelection_fnSetPara, + ITextSelection_fnGetStoryLength, + ITextSelection_fnGetStoryType, + ITextSelection_fnCollapse, + ITextSelection_fnExpand, + ITextSelection_fnGetIndex, + ITextSelection_fnSetIndex, + ITextSelection_fnSetRange, + ITextSelection_fnInRange, + ITextSelection_fnInStory, + ITextSelection_fnIsEqual, + ITextSelection_fnSelect, + ITextSelection_fnStartOf, + ITextSelection_fnEndOf, + ITextSelection_fnMove, + ITextSelection_fnMoveStart, + ITextSelection_fnMoveEnd, + ITextSelection_fnMoveWhile, + ITextSelection_fnMoveStartWhile, + ITextSelection_fnMoveEndWhile, + ITextSelection_fnMoveUntil, + ITextSelection_fnMoveStartUntil, + ITextSelection_fnMoveEndUntil, + ITextSelection_fnFindText, + ITextSelection_fnFindTextStart, + ITextSelection_fnFindTextEnd, + ITextSelection_fnDelete, + ITextSelection_fnCut, + ITextSelection_fnCopy, + ITextSelection_fnPaste, + ITextSelection_fnCanPaste, + ITextSelection_fnCanEdit, + ITextSelection_fnChangeCase, + ITextSelection_fnGetPoint, + ITextSelection_fnSetPoint, + ITextSelection_fnScrollIntoView, + ITextSelection_fnGetEmbeddedObject, + ITextSelection_fnGetFlags, + ITextSelection_fnSetFlags, + ITextSelection_fnGetType, + ITextSelection_fnMoveLeft, + ITextSelection_fnMoveRight, + ITextSelection_fnMoveUp, + ITextSelection_fnMoveDown, + ITextSelection_fnHomeKey, + ITextSelection_fnEndKey, + ITextSelection_fnTypeText +}; + +static ITextSelectionImpl * +CreateTextSelection(IRichEditOleImpl *reOle) +{ + ITextSelectionImpl *txtSel = heap_alloc(sizeof *txtSel); + if (!txtSel) + return NULL; + + txtSel->lpVtbl = &tsvt; + txtSel->ref = 1; + txtSel->reOle = reOle; + return txtSel; +} + LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) { IRichEditOleImpl *reo; @@ -544,6 +1535,12 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj) reo->lpTextDocumentVtbl = &tdvt; reo->ref = 1; reo->editor = editor; + reo->txtSel = CreateTextSelection(reo); + if (!reo->txtSel) + { + heap_free(reo); + return 0; + } TRACE("Created %p\n",reo); *ppObj = (LPVOID) reo; diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c index 0af3ba08012..a64c9f5a8db 100644 --- a/dlls/riched20/run.c +++ b/dlls/riched20/run.c @@ -241,11 +241,7 @@ void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) assert(p->member.run.nCharOfs != -1); ME_GetParagraph(p)->member.para.nFlags |= MEPF_REWRAP; - /* if we were at the end of screen line, and the next run is in the new - * line, then it's not the end of the line anymore */ - if (editor->bCaretAtEnd && editor->pCursors[0].pRun == pNext) - editor->bCaretAtEnd = FALSE; - /* Update all cursors so that they don't contain the soon deleted run */ + /* Update all cursors so that they don't contain the soon deleted run */ for (i=0; inCursors; i++) { if (editor->pCursors[i].pRun == pNext) { editor->pCursors[i].pRun = p; @@ -838,6 +834,7 @@ void ME_SetDefaultCharFormat(ME_TextEditor *editor, CHARFORMAT2W *mod) ME_Style *style; ME_UndoItem *undo; + /* FIXME: Should this be removed? It breaks a test. */ assert(mod->cbSize == sizeof(CHARFORMAT2W)); undo = ME_AddUndoItem(editor, diUndoSetDefaultCharFormat, NULL); if (undo) { diff --git a/dlls/riched20/string.c b/dlls/riched20/string.c index 2ec0092fcab..97b5a676684 100644 --- a/dlls/riched20/string.c +++ b/dlls/riched20/string.c @@ -128,7 +128,7 @@ ME_String *ME_VSplitString(ME_String *orig, int charidx) assert(charidx>=0); assert(charidx<=orig->nLen); - s = ME_MakeString(orig->szData+charidx); + s = ME_MakeStringN(orig->szData+charidx, orig->nLen-charidx); orig->nLen = charidx; orig->szData[charidx] = '\0'; return s; @@ -317,18 +317,10 @@ ME_WordBreakProc(LPWSTR s, INT start, INT len, INT code) return start; case WB_RIGHT: case WB_MOVEWORDRIGHT: - if (start && ME_IsWSpace(s[start - 1])) - { - while (start < len && ME_IsWSpace(s[start])) - start++; - } - else - { - while (start < len && !ME_IsWSpace(s[start])) - start++; - while (start < len && ME_IsWSpace(s[start])) - start++; - } + while (start < len && !ME_IsWSpace(s[start])) + start++; + while (start < len && ME_IsWSpace(s[start])) + start++; return start; } return 0; diff --git a/dlls/riched20/style.c b/dlls/riched20/style.c index b483be04863..66e45f5a832 100644 --- a/dlls/riched20/style.c +++ b/dlls/riched20/style.c @@ -221,6 +221,15 @@ ME_Style *ME_ApplyStyle(ME_Style *sSrc, CHARFORMAT2W *style) s->fmt.bUnderlineType = (style->dwEffects & CFM_UNDERLINE) ? CFU_CF1UNDERLINE : CFU_UNDERLINENONE; } + if (style->dwMask & CFM_BOLD && !(style->dwMask & CFM_WEIGHT)) + { + s->fmt.wWeight = (style->dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL; + } else if (style->dwMask & CFM_WEIGHT && !(style->dwMask & CFM_BOLD)) { + if (style->wWeight > FW_NORMAL) + s->fmt.dwEffects |= CFE_BOLD; + else + s->fmt.dwEffects &= ~CFE_BOLD; + } return s; } diff --git a/dlls/riched20/tests/Makefile.in b/dlls/riched20/tests/Makefile.in index 74a5686bf38..a3c425171b8 100644 --- a/dlls/riched20/tests/Makefile.in +++ b/dlls/riched20/tests/Makefile.in @@ -3,10 +3,11 @@ TOPOBJDIR = ../../.. SRCDIR = @srcdir@ VPATH = @srcdir@ TESTDLL = riched20.dll -IMPORTS = ole32 user32 gdi32 kernel32 +IMPORTS = uuid ole32 user32 gdi32 kernel32 CTESTS = \ - editor.c + editor.c \ + richole.c @MAKE_TEST_RULES@ diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index c9aa1949d9e..064e780a4b8 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -397,6 +397,123 @@ static void test_EM_SCROLLCARET(void) DestroyWindow(hwndRichEdit); } +static void test_EM_POSFROMCHAR(void) +{ + HWND hwndRichEdit = new_richedit(NULL); + int i; + LRESULT result; + unsigned int height = 0; + int xpos = 0; + static const char text[] = "aa\n" + "this is a long line of text that should be longer than the " + "control's width\n" + "cc\n" + "dd\n" + "ee\n" + "ff\n" + "gg\n" + "hh\n"; + + /* Fill the control to lines to ensure that most of them are offscreen */ + for (i = 0; i < 50; i++) + { + /* Do not modify the string; it is exactly 16 characters long. */ + SendMessage(hwndRichEdit, EM_SETSEL, 0, 0); + SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"0123456789ABCDE\n"); + } + + /* + Richedit 1.0 receives a POINTL* on wParam and character offset on lParam, returns void. + Richedit 2.0 receives character offset on wParam, ignores lParam, returns MAKELONG(x,y) + Richedit 3.0 accepts either of the above API conventions. + */ + + /* Testing Richedit 2.0 API format */ + + /* Testing start of lines. X-offset should be constant on all cases (native is 1). + Since all lines are identical and drawn with the same font, + they should have the same height... right? + */ + for (i = 0; i < 50; i++) + { + /* All the lines are 16 characters long */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, i * 16, 0); + if (i == 0) + { + ok(HIWORD(result) == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", HIWORD(result)); + todo_wine { + ok(LOWORD(result) == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result)); + } + xpos = LOWORD(result); + } + else if (i == 1) + { + ok(HIWORD(result) > 0, "EM_POSFROMCHAR reports y=%d, expected > 0\n", HIWORD(result)); + ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result)); + height = HIWORD(result); + } + else + { + ok(HIWORD(result) == i * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), i * height); + ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result)); + } + } + + /* Testing position at end of text */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, 50 * 16, 0); + ok(HIWORD(result) == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), 50 * height); + ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result)); + + /* Testing position way past end of text */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, 55 * 16, 0); + ok(HIWORD(result) == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), 50 * height); + ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result)); + + /* Testing that vertical scrolling does, in fact, have an effect on EM_POSFROMCHAR */ + SendMessage(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0); /* line down */ + for (i = 0; i < 50; i++) + { + /* All the lines are 16 characters long */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, i * 16, 0); + ok((signed short)(HIWORD(result)) == (i - 1) * height, + "EM_POSFROMCHAR reports y=%hd, expected %d\n", + (signed short)(HIWORD(result)), (i - 1) * height); + ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result)); + } + + /* Testing position at end of text */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, 50 * 16, 0); + ok(HIWORD(result) == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), (50 - 1) * height); + ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result)); + + /* Testing position way past end of text */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, 55 * 16, 0); + ok(HIWORD(result) == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", HIWORD(result), (50 - 1) * height); + ok(LOWORD(result) == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result)); + + /* Testing that horizontal scrolling does, in fact, have an effect on EM_POSFROMCHAR */ + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text); + SendMessage(hwndRichEdit, EM_SCROLL, SB_LINEUP, 0); /* line up */ + + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, 0, 0); + ok(HIWORD(result) == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", HIWORD(result)); + todo_wine { + ok(LOWORD(result) == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n", LOWORD(result)); + } + xpos = LOWORD(result); + + SendMessage(hwndRichEdit, WM_HSCROLL, SB_LINERIGHT, 0); + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, 0, 0); + ok(HIWORD(result) == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", HIWORD(result)); + todo_wine { + /* Fails on builtin because horizontal scrollbar is not being shown */ + ok((signed short)(LOWORD(result)) < xpos, + "EM_POSFROMCHAR reports x=%hd, expected value less than %d\n", + (signed short)(LOWORD(result)), xpos); + } + DestroyWindow(hwndRichEdit); +} + static void test_EM_SETCHARFORMAT(void) { HWND hwndRichEdit = new_richedit(NULL); @@ -452,6 +569,9 @@ static void test_EM_SETCHARFORMAT(void) rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) 0xfffffff0, (LPARAM) &cf2); ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc); + rc = SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0); + ok(rc == FALSE, "Should not be able to undo here.\n"); + SendMessage(hwndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0); /* A valid flag, CHARFORMAT2 structure minimally filled */ memset(&cf2, 0, sizeof(cf2)); @@ -459,6 +579,9 @@ static void test_EM_SETCHARFORMAT(void) rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_DEFAULT, (LPARAM) &cf2); ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc); + rc = SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0); + todo_wine ok(rc == FALSE, "Should not be able to undo here.\n"); + SendMessage(hwndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0); /* A valid flag, CHARFORMAT2 structure minimally filled */ memset(&cf2, 0, sizeof(cf2)); @@ -466,6 +589,9 @@ static void test_EM_SETCHARFORMAT(void) rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2); ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc); + rc = SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0); + ok(rc == FALSE, "Should not be able to undo here.\n"); + SendMessage(hwndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0); /* A valid flag, CHARFORMAT2 structure minimally filled */ memset(&cf2, 0, sizeof(cf2)); @@ -473,6 +599,9 @@ static void test_EM_SETCHARFORMAT(void) rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_WORD, (LPARAM) &cf2); ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc); + rc = SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0); + todo_wine ok(rc == TRUE, "Should not be able to undo here.\n"); + SendMessage(hwndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0); /* A valid flag, CHARFORMAT2 structure minimally filled */ memset(&cf2, 0, sizeof(cf2)); @@ -480,6 +609,9 @@ static void test_EM_SETCHARFORMAT(void) rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc); + rc = SendMessage(hwndRichEdit, EM_CANUNDO, 0, 0); + todo_wine ok(rc == TRUE, "Should not be able to undo here.\n"); + SendMessage(hwndRichEdit, EM_EMPTYUNDOBUFFER, 0, 0); cf2.cbSize = sizeof(CHARFORMAT2); SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT, @@ -540,6 +672,27 @@ static void test_EM_SETCHARFORMAT(void) hwndRichEdit = new_richedit(NULL); SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine"); + /* Need to set a TrueType font to get consistent CFM_BOLD results */ + memset(&cf2, 0, sizeof(CHARFORMAT2)); + cf2.cbSize = sizeof(CHARFORMAT2); + cf2.dwMask = CFM_FACE|CFM_WEIGHT; + cf2.dwEffects = 0; + strcpy(cf2.szFaceName, "Courier New"); + cf2.wWeight = FW_DONTCARE; + SendMessage(hwndRichEdit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cf2); + + memset(&cf2, 0, sizeof(CHARFORMAT2)); + cf2.cbSize = sizeof(CHARFORMAT2); + SendMessage(hwndRichEdit, EM_SETSEL, 0, 4); + SendMessage(hwndRichEdit, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf2); + ok ((((tested_effects[i] == CFE_SUBSCRIPT || tested_effects[i] == CFE_SUPERSCRIPT) && + (cf2.dwMask & CFM_SUPERSCRIPT) == CFM_SUPERSCRIPT) + || + (cf2.dwMask & tested_effects[i]) == tested_effects[i]), + "%d, cf2.dwMask == 0x%08x expected mask 0x%08x\n", i, cf2.dwMask, tested_effects[i]); + ok((cf2.dwEffects & tested_effects[i]) == 0, + "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x clear\n", i, cf2.dwEffects, tested_effects[i]); + memset(&cf2, 0, sizeof(CHARFORMAT2)); cf2.cbSize = sizeof(CHARFORMAT2); cf2.dwMask = tested_effects[i]; @@ -582,8 +735,6 @@ static void test_EM_SETCHARFORMAT(void) || (cf2.dwMask & tested_effects[i]) == 0), "%d, cf2.dwMask == 0x%08x expected mask 0x%08x clear\n", i, cf2.dwMask, tested_effects[i]); - ok((cf2.dwEffects & tested_effects[i]) == 0, - "%d, cf2.dwEffects == 0x%08x expected effect 0x%08x clear\n", i, cf2.dwEffects, tested_effects[i]); DestroyWindow(hwndRichEdit); } @@ -593,6 +744,15 @@ static void test_EM_SETCHARFORMAT(void) hwndRichEdit = new_richedit(NULL); SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"wine"); + /* Need to set a TrueType font to get consistent CFM_BOLD results */ + memset(&cf2, 0, sizeof(CHARFORMAT2)); + cf2.cbSize = sizeof(CHARFORMAT2); + cf2.dwMask = CFM_FACE|CFM_WEIGHT; + cf2.dwEffects = 0; + strcpy(cf2.szFaceName, "Courier New"); + cf2.wWeight = FW_DONTCARE; + SendMessage(hwndRichEdit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cf2); + memset(&cf2, 0, sizeof(CHARFORMAT2)); cf2.cbSize = sizeof(CHARFORMAT2); cf2.dwMask = tested_effects[i]; @@ -1921,16 +2081,6 @@ static void test_EM_SCROLL(void) int expr; /* expected return value */ HWND hwndRichEdit = new_richedit(NULL); int y_before, y_after; /* units of lines of text */ - SCROLLINFO si; - - /* Empty richedit should have scroll range of 0 */ - si.cbSize = sizeof(si); - si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; - GetScrollInfo(hwndRichEdit, SB_VERT, &si); - ok(si.nMin == 0, "si.nMin == %d, expected 0\n", si.nMin); - ok(si.nMax == 0, "si.nMax == %d, expected 0\n", si.nMax); - ok(si.nPos == 0, "si.nPos == %d, expected 0\n", si.nPos); - ok(si.nPage == 0, "si.nPage == %d, expected 0\n", si.nPage); /* test a richedit box containing a single line of text */ SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "a");/* one line of text */ @@ -3481,6 +3631,30 @@ static DWORD CALLBACK test_EM_STREAMIN_esCallback(DWORD_PTR dwCookie, return 0; } +struct StringWithLength { + int length; + char *buffer; +}; + +/* This callback is used to handled the null characters in a string. */ +static DWORD CALLBACK test_EM_STREAMIN_esCallback2(DWORD_PTR dwCookie, + LPBYTE pbBuff, + LONG cb, + LONG *pcb) +{ + struct StringWithLength* str = (struct StringWithLength*)dwCookie; + int size = str->length; + *pcb = cb; + if (*pcb > size) { + *pcb = size; + } + if (*pcb > 0) { + memcpy(pbBuff, str->buffer, *pcb); + str->buffer += *pcb; + str->length -= *pcb; + } + return 0; +} static void test_EM_STREAMIN(void) { @@ -3510,6 +3684,15 @@ static void test_EM_STREAMIN(void) const char * streamText3 = "RichEdit1"; + struct StringWithLength cookieForStream4; + const char * streamText4 = + "This text just needs to be long enough to cause run to be split onto "\ + "two seperate lines and make sure the null terminating character is "\ + "handled properly.\0"; + int length4 = strlen(streamText4) + 1; + cookieForStream4.buffer = (char *)streamText4; + cookieForStream4.length = length4; + /* Minimal test without \par at the end */ es.dwCookie = (DWORD_PTR)&streamText0; es.dwError = 0; @@ -3593,6 +3776,17 @@ static void test_EM_STREAMIN(void) "EM_STREAMIN: Test 3 set wrong text: Result: %s\n",buffer); ok(es.dwError == -16, "EM_STREAMIN: Test 3 set error %d, expected %d\n", es.dwError, -16); + es.dwCookie = (DWORD_PTR)&cookieForStream4; + es.dwError = 0; + es.pfnCallback = test_EM_STREAMIN_esCallback2; + SendMessage(hwndRichEdit, EM_STREAMIN, + (WPARAM)(SF_TEXT), (LPARAM)&es); + + result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); + ok (result == length4, + "EM_STREAMIN: Test 4 returned %ld, expected %d\n", result, length4); + ok(es.dwError == 0, "EM_STREAMIN: Test 4 set error %d, expected %d\n", es.dwError, 0); + DestroyWindow(hwndRichEdit); } @@ -4158,6 +4352,208 @@ static void test_WM_NOTIFY(void) DestroyWindow(parent); } +static void simulate_typing_characters(HWND hwnd, const char* szChars) +{ + int ret; + + while (*szChars != '\0') { + SendMessageA(hwnd, WM_KEYDOWN, *szChars, 1); + ret = SendMessageA(hwnd, WM_CHAR, *szChars, 1); + ok(ret == 0, "WM_CHAR('%c') ret=%d\n", *szChars, ret); + SendMessageA(hwnd, WM_KEYUP, *szChars, 1); + szChars++; + } +} + +static void test_undo_coalescing(void) +{ + HWND hwnd; + int result; + char buffer[64] = {0}; + + /* multi-line control inserts CR normally */ + hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP|ES_MULTILINE, + 0, 0, 200, 60, 0, 0, 0, 0); + ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError()); + + result = SendMessage(hwnd, EM_CANUNDO, 0, 0); + ok (result == FALSE, "Can undo after window creation.\n"); + result = SendMessage(hwnd, EM_UNDO, 0, 0); + ok (result == FALSE, "Undo operation successful with nothing to undo.\n"); + result = SendMessage(hwnd, EM_CANREDO, 0, 0); + ok (result == FALSE, "Can redo after window creation.\n"); + result = SendMessage(hwnd, EM_REDO, 0, 0); + ok (result == FALSE, "Redo operation successful with nothing undone.\n"); + + /* Test the effect of arrows keys during typing on undo transactions*/ + simulate_typing_characters(hwnd, "one two three"); + SendMessage(hwnd, WM_KEYDOWN, VK_RIGHT, 1); + SendMessage(hwnd, WM_KEYUP, VK_RIGHT, 1); + simulate_typing_characters(hwnd, " four five six"); + + result = SendMessage(hwnd, EM_CANREDO, 0, 0); + ok (result == FALSE, "Can redo before anything is undone.\n"); + result = SendMessage(hwnd, EM_CANUNDO, 0, 0); + ok (result == TRUE, "Cannot undo typed characters.\n"); + result = SendMessage(hwnd, EM_UNDO, 0, 0); + ok (result == TRUE, "EM_UNDO Failed to undo typed characters.\n"); + result = SendMessage(hwnd, EM_CANREDO, 0, 0); + ok (result == TRUE, "Cannot redo after undo.\n"); + SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer); + result = strcmp(buffer, "one two three"); + ok (result == 0, "expected '%s' but got '%s'\n", "one two three", buffer); + + result = SendMessage(hwnd, EM_CANUNDO, 0, 0); + ok (result == TRUE, "Cannot undo typed characters.\n"); + result = SendMessage(hwnd, WM_UNDO, 0, 0); + ok (result == TRUE, "Failed to undo typed characters.\n"); + SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer); + result = strcmp(buffer, ""); + ok (result == 0, "expected '%s' but got '%s'\n", "", buffer); + + /* Test the effect of focus changes during typing on undo transactions*/ + simulate_typing_characters(hwnd, "one two three"); + result = SendMessage(hwnd, EM_CANREDO, 0, 0); + ok (result == FALSE, "Redo buffer should have been cleared by typing.\n"); + SendMessage(hwnd, WM_KILLFOCUS, (WPARAM)NULL, 0); + SendMessage(hwnd, WM_SETFOCUS, (WPARAM)NULL, 0); + simulate_typing_characters(hwnd, " four five six"); + result = SendMessage(hwnd, EM_UNDO, 0, 0); + ok (result == TRUE, "Failed to undo typed characters.\n"); + SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer); + result = strcmp(buffer, "one two three"); + ok (result == 0, "expected '%s' but got '%s'\n", "one two three", buffer); + + /* Test the effect of the back key during typing on undo transactions */ + SendMessage(hwnd, EM_EMPTYUNDOBUFFER, 0, 0); + result = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)""); + ok (result == TRUE, "Failed to clear the text.\n"); + simulate_typing_characters(hwnd, "one two threa"); + result = SendMessage(hwnd, EM_CANREDO, 0, 0); + ok (result == FALSE, "Redo buffer should have been cleared by typing.\n"); + SendMessage(hwnd, WM_KEYDOWN, VK_BACK, 1); + SendMessage(hwnd, WM_KEYUP, VK_BACK, 1); + simulate_typing_characters(hwnd, "e four five six"); + result = SendMessage(hwnd, EM_UNDO, 0, 0); + ok (result == TRUE, "Failed to undo typed characters.\n"); + SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer); + result = strcmp(buffer, ""); + ok (result == 0, "expected '%s' but got '%s'\n", "", buffer); + + /* Test the effect of the delete key during typing on undo transactions */ + SendMessage(hwnd, EM_EMPTYUNDOBUFFER, 0, 0); + result = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"abcd"); + ok(result == TRUE, "Failed to set the text.\n"); + SendMessage(hwnd, EM_SETSEL, (WPARAM)1, (LPARAM)1); + SendMessage(hwnd, WM_KEYDOWN, VK_DELETE, 1); + SendMessage(hwnd, WM_KEYUP, VK_DELETE, 1); + SendMessage(hwnd, WM_KEYDOWN, VK_DELETE, 1); + SendMessage(hwnd, WM_KEYUP, VK_DELETE, 1); + result = SendMessage(hwnd, EM_UNDO, 0, 0); + ok (result == TRUE, "Failed to undo typed characters.\n"); + SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer); + result = strcmp(buffer, "acd"); + ok (result == 0, "expected '%s' but got '%s'\n", "acd", buffer); + result = SendMessage(hwnd, EM_UNDO, 0, 0); + ok (result == TRUE, "Failed to undo typed characters.\n"); + SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer); + result = strcmp(buffer, "abcd"); + ok (result == 0, "expected '%s' but got '%s'\n", "abcd", buffer); + + /* Test the effect of EM_STOPGROUPTYPING on undo transactions*/ + SendMessage(hwnd, EM_EMPTYUNDOBUFFER, 0, 0); + result = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)""); + ok (result == TRUE, "Failed to clear the text.\n"); + simulate_typing_characters(hwnd, "one two three"); + result = SendMessage(hwnd, EM_STOPGROUPTYPING, 0, 0); + ok (result == 0, "expected %d but got %d\n", 0, result); + simulate_typing_characters(hwnd, " four five six"); + result = SendMessage(hwnd, EM_UNDO, 0, 0); + ok (result == TRUE, "Failed to undo typed characters.\n"); + SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer); + result = strcmp(buffer, "one two three"); + ok (result == 0, "expected '%s' but got '%s'\n", "one two three", buffer); + result = SendMessage(hwnd, EM_UNDO, 0, 0); + ok (result == TRUE, "Failed to undo typed characters.\n"); + ok (result == TRUE, "Failed to undo typed characters.\n"); + SendMessageA(hwnd, WM_GETTEXT, sizeof(buffer), (LPARAM)buffer); + result = strcmp(buffer, ""); + ok (result == 0, "expected '%s' but got '%s'\n", "", buffer); + + DestroyWindow(hwnd); +} + +/* Used to simulate a Ctrl-Arrow Key press. */ +#define SEND_CTRL_EXT_KEY(hwnd, vk, scancode) \ + keybd_event(VK_CONTROL, 0x1d, 0, 0);\ + keybd_event(vk, scancode, KEYEVENTF_EXTENDEDKEY, 0);\ + keybd_event(vk, scancode | 0x80, KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY, 0);\ + keybd_event(VK_CONTROL, 0x1d | 0x80, KEYEVENTF_KEYUP, 0); \ + while (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) { \ + TranslateMessage(&msg); \ + DispatchMessage(&msg); \ + } +#define SEND_CTRL_LEFT(hwnd) SEND_CTRL_EXT_KEY(hwnd, VK_LEFT, 0x4b) +#define SEND_CTRL_RIGHT(hwnd) SEND_CTRL_EXT_KEY(hwnd, VK_RIGHT, 0x4d) + +static void test_word_movement(){ + HWND hwnd; + int result; + int sel_start, sel_end; + MSG msg; + + /* multi-line control inserts CR normally */ + hwnd = new_richedit(NULL); + + SendMessage(hwnd, WM_SETFOCUS, (WPARAM)hwnd, 0); + result = SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"one two three"); + ok (result == TRUE, "Failed to clear the text.\n"); + SendMessage(hwnd, EM_SETSEL, 0, 0); + /* |one two three */ + + SEND_CTRL_RIGHT(hwnd) + /* one |two three */ + SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); + ok(sel_start == sel_end, "Selection should be empty\n"); + ok(sel_start == 4, "Cursur is at %d instead of %d\n", sel_start, 4); + + SEND_CTRL_RIGHT(hwnd) + /* one two |three */ + SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); + ok(sel_start == sel_end, "Selection should be empty\n"); + ok(sel_start == 9, "Cursur is at %d instead of %d\n", sel_start, 9); + + SEND_CTRL_LEFT(hwnd) + /* one |two three */ + SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); + ok(sel_start == sel_end, "Selection should be empty\n"); + ok(sel_start == 4, "Cursur is at %d instead of %d\n", sel_start, 4); + + SEND_CTRL_LEFT(hwnd) + /* |one two three */ + SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); + ok(sel_start == sel_end, "Selection should be empty\n"); + ok(sel_start == 0, "Cursur is at %d instead of %d\n", sel_start, 0); + + SendMessage(hwnd, EM_SETSEL, 8, 8); + /* one two | three */ + SEND_CTRL_RIGHT(hwnd) + /* one two |three */ + SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); + ok(sel_start == sel_end, "Selection should be empty\n"); + ok(sel_start == 9, "Cursur is at %d instead of %d\n", sel_start, 9); + + SendMessage(hwnd, EM_SETSEL, 11, 11); + /* one two th|ree */ + SEND_CTRL_LEFT(hwnd) + /* one two |three */ + SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel_start, (LPARAM)&sel_end); + ok(sel_start == sel_end, "Selection should be empty\n"); + ok(sel_start == 9, "Cursur is at %d instead of %d\n", sel_start, 9); + + DestroyWindow(hwnd); +} + START_TEST( editor ) { MSG msg; @@ -4170,6 +4566,7 @@ START_TEST( editor ) test_WM_CHAR(); test_EM_FINDTEXT(); test_EM_GETLINE(); + test_EM_POSFROMCHAR(); test_EM_SCROLLCARET(); test_EM_SCROLL(); test_WM_SETTEXT(); @@ -4202,6 +4599,8 @@ START_TEST( editor ) test_WM_NOTIFY(); test_EM_AUTOURLDETECT(); test_eventMask(); + test_undo_coalescing(); + test_word_movement(); /* Set the environment variable WINETEST_RICHED20 to keep windows * responsive and open for 30 seconds. This is useful for debugging. diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c new file mode 100644 index 00000000000..f6c2928e3d0 --- /dev/null +++ b/dlls/riched20/tests/richole.c @@ -0,0 +1,120 @@ +/* + * Tests for IRichEditOle and friends. + * + * Copyright 2008 Google (Dan Hipschman) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +DEFINE_GUID(IID_ITextDocument, 0x8cc497c0, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); +DEFINE_GUID(IID_ITextRange, 0x8cc497c2, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); +DEFINE_GUID(IID_ITextSelection, 0x8cc497c1, 0xa1df, 0x11ce, 0x80, 0x98, 0x00, 0xaa, 0x00, 0x47, 0xbe, 0x5d); + +static HMODULE hmoduleRichEdit; + +static HWND new_window(LPCTSTR lpClassName, DWORD dwStyle, HWND parent) +{ + HWND hwnd + = CreateWindow(lpClassName, NULL, + dwStyle | WS_POPUP | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE, + 0, 0, 200, 60, parent, NULL, hmoduleRichEdit, NULL); + ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError()); + return hwnd; +} + +static HWND new_richedit(HWND parent) +{ + return new_window(RICHEDIT_CLASS, ES_MULTILINE, parent); +} + + +START_TEST(richole) +{ + IRichEditOle *reOle = NULL; + ITextDocument *txtDoc = NULL; + ITextSelection *txtSel = NULL; + IUnknown *punk; + HRESULT hres; + LRESULT res; + HWND w; + + /* Must explicitly LoadLibrary(). The test has no references to functions in + * RICHED20.DLL, so the linker doesn't actually link to it. */ + hmoduleRichEdit = LoadLibrary("RICHED20.DLL"); + ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError()); + + w = new_richedit(NULL); + if (!w) { + skip("Couldn't create window\n"); + return; + } + + res = SendMessage(w, EM_GETOLEINTERFACE, 0, (LPARAM) &reOle); + ok(res, "SendMessage\n"); + ok(reOle != NULL, "EM_GETOLEINTERFACE\n"); + + hres = IUnknown_QueryInterface(reOle, &IID_ITextDocument, + (void **) &txtDoc); + ok(hres == S_OK, "IRichEditOle_QueryInterface\n"); + ok(txtDoc != NULL, "IRichEditOle_QueryInterface\n"); + + hres = ITextDocument_GetSelection(txtDoc, &txtSel); + ok(hres == S_OK, "ITextDocument_GetSelection\n"); + ok(txtSel != NULL, "ITextDocument_GetSelection\n"); + + punk = NULL; + hres = ITextSelection_QueryInterface(txtSel, &IID_ITextSelection, (void **) &punk); + ok(hres == S_OK, "ITextSelection_QueryInterface\n"); + ok(punk != NULL, "ITextSelection_QueryInterface\n"); + IUnknown_Release(punk); + + punk = NULL; + hres = ITextSelection_QueryInterface(txtSel, &IID_ITextRange, (void **) &punk); + ok(hres == S_OK, "ITextSelection_QueryInterface\n"); + ok(punk != NULL, "ITextSelection_QueryInterface\n"); + IUnknown_Release(punk); + + punk = NULL; + hres = ITextSelection_QueryInterface(txtSel, &IID_IDispatch, (void **) &punk); + ok(hres == S_OK, "ITextSelection_QueryInterface\n"); + ok(punk != NULL, "ITextSelection_QueryInterface\n"); + IUnknown_Release(punk); + + ITextDocument_Release(txtDoc); + IUnknown_Release(reOle); + DestroyWindow(w); + + /* Methods should return CO_E_RELEASED if the backing document has + been released. One test should suffice. */ + hres = ITextSelection_CanEdit(txtSel, NULL); + ok(hres == CO_E_RELEASED, "ITextSelection after ITextDocument destroyed\n"); + + ITextSelection_Release(txtSel); +} diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c index a26f0e07eb1..a0fd646eca3 100644 --- a/dlls/riched20/undo.c +++ b/dlls/riched20/undo.c @@ -55,10 +55,20 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp return NULL; else { - ME_DisplayItem *pItem = (ME_DisplayItem *)ALLOC_OBJ(ME_UndoItem); + ME_DisplayItem *pItem; + if (editor->pUndoStack + && editor->pUndoStack->type == diUndoPotentialEndTransaction) + { + editor->pUndoStack->type = diUndoEndTransaction; + } + pItem = (ME_DisplayItem *)ALLOC_OBJ(ME_UndoItem); ((ME_UndoItem *)pItem)->nCR = ((ME_UndoItem *)pItem)->nLF = -1; switch(type) { + case diUndoPotentialEndTransaction: + /* only should be added for manually typed chars, not undos or redos */ + assert(editor->nUndoMode == umAddToUndo); + /* intentional fall-through to next case */ case diUndoEndTransaction: break; case diUndoSetParagraphFormat: @@ -105,7 +115,7 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp TRACE("Pushing id=%s to undo stack\n", ME_GetDITypeName(type)); pItem->next = editor->pUndoStack; - if (type == diUndoEndTransaction) + if (type == diUndoEndTransaction || type == diUndoPotentialEndTransaction) editor->nUndoStackSize++; if (editor->pUndoStack) editor->pUndoStack->prev = pItem; @@ -154,6 +164,18 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp } } +/** + * Commits preceding changes into a transaction that can be undone together. + * + * This should be called after all the changes occur associated with an event + * so that the group of changes can be undone atomically as a transaction. + * + * This will have no effect the undo mode is set to ignore changes, or if no + * changes preceded calling this function before the last time it was called. + * + * This can also be used to conclude a coalescing transaction (used for grouping + * typed characters). + */ void ME_CommitUndo(ME_TextEditor *editor) { if (editor->nUndoMode == umIgnore) return; @@ -168,10 +190,84 @@ void ME_CommitUndo(ME_TextEditor *editor) { if (editor->pUndoStack->type == diUndoEndTransaction) return; + if (editor->pUndoStack->type == diUndoPotentialEndTransaction) + { + /* Previous transaction was as a result of characters typed, + * so the end of this transaction is confirmed. */ + editor->pUndoStack->type = diUndoEndTransaction; + return; + } + ME_AddUndoItem(editor, diUndoEndTransaction, NULL); ME_SendSelChange(editor); } +/** + * Groups supsequent changes with previous ones for an undo if coalescing. + * + * Has no effect if the previous changes were followed by a ME_CommitUndo. This + * function will only have an affect if the previous changes were followed by + * a call to ME_CommitCoalescingUndo, which allows the transaction to be + * continued. + * + * This allows multiple consecutively typed characters to be grouped together + * to be undone by a single undo operation. + */ +void ME_ContinueCoalescingTransaction(ME_TextEditor *editor) +{ + ME_DisplayItem* p; + + if (editor->nUndoMode == umIgnore) + return; + + assert(editor->nUndoMode == umAddToUndo); + + p = editor->pUndoStack; + + if (p && p->type == diUndoPotentialEndTransaction) { + assert(p->next); /* EndTransactions shouldn't be at bottom of undo stack */ + editor->pUndoStack = p->next; + editor->pUndoStack->prev = NULL; + editor->nUndoStackSize--; + ME_DestroyDisplayItem(p); + } +} + +/** + * Commits preceding changes into a undo transaction that can be expanded. + * + * This function allows the transaction to be reopened with + * ME_ContinueCoalescingTransaction in order to continue the transaction. If an + * undo item is added to the undo stack as a result of a change without the + * transaction being reopened, then the transaction will be ended, and the + * changes will become a part of the next transaction. + * + * This is used to allow typed characters to be grouped together since each + * typed character results in a single event, and each event adding undo items + * must be committed. Using this function as opposed to ME_CommitUndo allows + * multiple events to be grouped, and undone together. + */ +void ME_CommitCoalescingUndo(ME_TextEditor *editor) +{ + if (editor->nUndoMode == umIgnore) + return; + + assert(editor->nUndoMode == umAddToUndo); + + /* no transactions, no need to commit */ + if (!editor->pUndoStack) + return; + + /* no need to commit empty transactions */ + if (editor->pUndoStack->type == diUndoEndTransaction) + return; + if (editor->pUndoStack->type == diUndoPotentialEndTransaction) + return; + + ME_AddUndoItem(editor, diUndoPotentialEndTransaction, NULL); + ME_SendSelChange(editor); +} + static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem) { ME_UndoItem *pUItem = (ME_UndoItem *)pItem; @@ -182,6 +278,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem) switch(pItem->type) { + case diUndoPotentialEndTransaction: case diUndoEndTransaction: assert(0); case diUndoSetParagraphFormat: @@ -239,20 +336,21 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem) } } -void ME_Undo(ME_TextEditor *editor) { +BOOL ME_Undo(ME_TextEditor *editor) { ME_DisplayItem *p; ME_UndoMode nMode = editor->nUndoMode; if (editor->nUndoMode == umIgnore) - return; + return FALSE; assert(nMode == umAddToUndo || nMode == umIgnore); /* no undo items ? */ if (!editor->pUndoStack) - return; + return FALSE; /* watch out for uncommitted transactions ! */ - assert(editor->pUndoStack->type == diUndoEndTransaction); + assert(editor->pUndoStack->type == diUndoEndTransaction + || editor->pUndoStack->type == diUndoPotentialEndTransaction); editor->nUndoMode = umAddToRedo; p = editor->pUndoStack->next; @@ -270,19 +368,20 @@ void ME_Undo(ME_TextEditor *editor) { p->prev = NULL; editor->nUndoMode = nMode; ME_UpdateRepaint(editor); + return TRUE; } -void ME_Redo(ME_TextEditor *editor) { +BOOL ME_Redo(ME_TextEditor *editor) { ME_DisplayItem *p; ME_UndoMode nMode = editor->nUndoMode; assert(nMode == umAddToUndo || nMode == umIgnore); if (editor->nUndoMode == umIgnore) - return; + return FALSE; /* no redo items ? */ if (!editor->pRedoStack) - return; + return FALSE; /* watch out for uncommitted transactions ! */ assert(editor->pRedoStack->type == diUndoEndTransaction); @@ -302,4 +401,5 @@ void ME_Redo(ME_TextEditor *editor) { p->prev = NULL; editor->nUndoMode = nMode; ME_UpdateRepaint(editor); + return TRUE; } diff --git a/dlls/riched20/wrap.c b/dlls/riched20/wrap.c index da5fef7359f..adabea13803 100644 --- a/dlls/riched20/wrap.c +++ b/dlls/riched20/wrap.c @@ -58,21 +58,47 @@ static void ME_BeginRow(ME_WrapContext *wc) static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) { ME_DisplayItem *p, *row, *para; + BOOL bSkippingSpaces = TRUE; int ascent = 0, descent = 0, width=0, shift = 0, align = 0; /* wrap text */ para = ME_GetParagraph(wc->pRowStart); - for (p = wc->pRowStart; p!=pEnd; p = p->next) + + for (p = pEnd->prev; p!=wc->pRowStart->prev; p = p->prev) { - /* ENDPARA run shouldn't affect row height, except if it's the only run in the paragraph */ - if (p->type==diRun && ((p==wc->pRowStart) || !(p->member.run.nFlags & MERF_ENDPARA))) { /* FIXME add more run types */ - if (p->member.run.nAscent>ascent) - ascent = p->member.run.nAscent; - if (p->member.run.nDescent>descent) - descent = p->member.run.nDescent; - if (!(p->member.run.nFlags & (MERF_ENDPARA|MERF_SKIPPED))) - width += p->member.run.nWidth; - } + /* ENDPARA run shouldn't affect row height, except if it's the only run in the paragraph */ + if (p->type==diRun && ((p==wc->pRowStart) || !(p->member.run.nFlags & MERF_ENDPARA))) { /* FIXME add more run types */ + if (p->member.run.nAscent>ascent) + ascent = p->member.run.nAscent; + if (p->member.run.nDescent>descent) + descent = p->member.run.nDescent; + if (bSkippingSpaces) + { + /* Exclude space characters from run width. + * Other whitespace or delimiters are not treated this way. */ + SIZE sz; + int len = p->member.run.strText->nLen; + WCHAR *text = p->member.run.strText->szData + len - 1; + + assert (len); + while (len && *(text--) == ' ') + len--; + if (len) + { + if (len == p->member.run.strText->nLen) + { + width += p->member.run.nWidth; + } else { + sz = ME_GetRunSize(wc->context, ¶->member.para, + &p->member.run, len, p->member.run.pt.x); + width += sz.cx; + } + } + bSkippingSpaces = !len; + } else if (!(p->member.run.nFlags & MERF_ENDPARA)) + width += p->member.run.nWidth; + } } + row = ME_MakeRow(ascent+descent, ascent, width); row->member.row.nYPos = wc->pt.y; row->member.row.nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin); @@ -98,7 +124,7 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd) static void ME_WrapEndParagraph(ME_WrapContext *wc, ME_DisplayItem *p) { if (wc->pRowStart) - ME_InsertRowStart(wc, p->next); + ME_InsertRowStart(wc, p); /* p = p->member.para.prev_para->next; @@ -471,6 +497,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { ME_Context c; BOOL bModified = FALSE; int yStart = -1; + int yLastPos = 0; ME_InitContext(&c, editor, GetDC(editor->hWnd)); editor->nHeight = 0; @@ -496,6 +523,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { bModified = bModified | bRedraw; + yLastPos = c.pt.y; c.pt.y += item->member.para.nHeight; item = item->member.para.next_para; } @@ -503,6 +531,7 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) { editor->sizeWindow.cy = c.rcView.bottom-c.rcView.top; editor->nTotalLength = c.pt.y; + editor->pBuffer->pLast->member.para.nYPos = yLastPos; ME_DestroyContext(&c, editor->hWnd); diff --git a/dlls/riched32/richedit.c b/dlls/riched32/richedit.c index d13de2f4626..2640f8dbb2d 100644 --- a/dlls/riched32/richedit.c +++ b/dlls/riched32/richedit.c @@ -56,7 +56,7 @@ static BOOL RICHED32_Register(void) WNDCLASSA wndClass; ZeroMemory(&wndClass, sizeof(WNDCLASSA)); - wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS; + wndClass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS; wndClass.lpfnWndProc = RichEdit10ANSIWndProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 4; diff --git a/dlls/riched32/tests/editor.c b/dlls/riched32/tests/editor.c index ff82654ff6e..63a63f13018 100644 --- a/dlls/riched32/tests/editor.c +++ b/dlls/riched32/tests/editor.c @@ -696,6 +696,130 @@ static void test_EM_FINDTEXT(void) DestroyWindow(hwndRichEdit); } +static void test_EM_POSFROMCHAR(void) +{ + HWND hwndRichEdit = new_richedit(NULL); + int i; + POINTL pl; + LRESULT result; + unsigned int height = 0; + int xpos = 0; + static const char text[] = "aa\n" + "this is a long line of text that should be longer than the " + "control's width\n" + "cc\n" + "dd\n" + "ee\n" + "ff\n" + "gg\n" + "hh\n"; + + /* Fill the control to lines to ensure that most of them are offscreen */ + for (i = 0; i < 50; i++) + { + /* Do not modify the string; it is exactly 16 characters long. */ + SendMessage(hwndRichEdit, EM_SETSEL, 0, 0); + SendMessage(hwndRichEdit, EM_REPLACESEL, 0, (LPARAM)"0123456789ABCD\r\n"); + } + + /* + Richedit 1.0 receives a POINTL* on wParam and character offset on lParam, returns void. + Richedit 2.0 receives character offset on wParam, ignores lParam, returns MAKELONG(x,y) + Richedit 3.0 accepts either of the above API conventions. + */ + + /* Testing Richedit 1.0 API format */ + + /* Testing start of lines. X-offset should be constant on all cases (native is 1). + Since all lines are identical and drawn with the same font, + they should have the same height... right? + */ + for (i = 0; i < 50; i++) + { + /* All the lines are 16 characters long */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, i * 16); + ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result); + if (i == 0) + { + ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y); + todo_wine { + ok(pl.x == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); + } + xpos = pl.x; + } + else if (i == 1) + { + ok(pl.y > 0, "EM_POSFROMCHAR reports y=%d, expected > 0\n", pl.y); + ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); + height = pl.y; + } + else + { + ok(pl.y == i * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, i * height); + ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); + } + } + + /* Testing position at end of text */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 50 * 16); + ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result); + ok(pl.y == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, 50 * height); + ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); + + /* Testing position way past end of text */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 55 * 16); + ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result); + ok(pl.y == 50 * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, 50 * height); + ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); + + + /* Testing that vertical scrolling does, in fact, have an effect on EM_POSFROMCHAR */ + SendMessage(hwndRichEdit, EM_SCROLL, SB_LINEDOWN, 0); /* line down */ + for (i = 0; i < 50; i++) + { + /* All the lines are 16 characters long */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, i * 16); + ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result); + ok(pl.y == (i - 1) * height, + "EM_POSFROMCHAR reports y=%d, expected %d\n", + pl.y, (i - 1) * height); + ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); + } + + /* Testing position at end of text */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 50 * 16); + ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result); + ok(pl.y == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, (50 - 1) * height); + ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); + + /* Testing position way past end of text */ + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 55 * 16); + ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result); + ok(pl.y == (50 - 1) * height, "EM_POSFROMCHAR reports y=%d, expected %d\n", pl.y, (50 - 1) * height); + ok(pl.x == xpos, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); + + /* Testing that horizontal scrolling does, in fact, have an effect on EM_POSFROMCHAR */ + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text); + SendMessage(hwndRichEdit, EM_SCROLL, SB_LINEUP, 0); /* line up */ + + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 0); + ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result); + ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y); + todo_wine { + ok(pl.x == 1, "EM_POSFROMCHAR reports x=%d, expected 1\n", pl.x); + } + xpos = pl.x; + + SendMessage(hwndRichEdit, WM_HSCROLL, SB_LINERIGHT, 0); + result = SendMessage(hwndRichEdit, EM_POSFROMCHAR, (WPARAM)&pl, 0); + ok(result == 0, "EM_POSFROMCHAR returned %ld, expected 0\n", result); + ok(pl.y == 0, "EM_POSFROMCHAR reports y=%d, expected 0\n", pl.y); + todo_wine { + /* Fails on builtin because horizontal scrollbar is not being shown */ + ok(pl.x < xpos, "EM_POSFROMCHAR reports x=%hd, expected value less than %d\n", pl.x, xpos); + } + DestroyWindow(hwndRichEdit); +} START_TEST( editor ) @@ -717,6 +841,7 @@ START_TEST( editor ) test_EM_GETLINE(); test_EM_LINELENGTH(); test_EM_FINDTEXT(); + test_EM_POSFROMCHAR(); /* Set the environment variable WINETEST_RICHED32 to keep windows * responsive and open for 30 seconds. This is useful for debugging. diff --git a/dlls/rpcrt4/Makefile.in b/dlls/rpcrt4/Makefile.in index fed47461e18..8672ced5078 100644 --- a/dlls/rpcrt4/Makefile.in +++ b/dlls/rpcrt4/Makefile.in @@ -25,11 +25,13 @@ C_SRCS = \ rpc_message.c \ rpc_server.c \ rpc_transport.c \ - rpcrt4_main.c \ - rpcss_np_client.c + rpcrt4_main.c RC_SRCS = version.rc +IDL_C_SRCS = \ + epm.idl + @MAKE_DLL_RULES@ @DEPENDENCIES@ # everything below this line is overwritten by make depend diff --git a/dlls/rpcrt4/rpcss_np_client.h b/dlls/rpcrt4/epm.idl similarity index 73% copy from dlls/rpcrt4/rpcss_np_client.h copy to dlls/rpcrt4/epm.idl index b00066de518..67fad348c88 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/dlls/rpcrt4/epm.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Robert Shearman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,4 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H - -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/epm.idl" diff --git a/dlls/rpcrt4/epm_towers.h b/dlls/rpcrt4/epm_towers.h index 7570cc2e846..f38d4872872 100644 --- a/dlls/rpcrt4/epm_towers.h +++ b/dlls/rpcrt4/epm_towers.h @@ -19,6 +19,8 @@ * */ +#include "wine/epm.h" + #define EPM_PROTOCOL_DNET_NSP 0x04 #define EPM_PROTOCOL_OSI_TP4 0x05 #define EPM_PROTOCOL_OSI_CLNS 0x06 @@ -48,10 +50,6 @@ #include -typedef unsigned char u_int8; -typedef unsigned short u_int16; -typedef unsigned int u_int32; - typedef struct { u_int16 count_lhs; diff --git a/dlls/rpcrt4/ndr_clientserver.c b/dlls/rpcrt4/ndr_clientserver.c index 1afab2a6218..9af736a020f 100644 --- a/dlls/rpcrt4/ndr_clientserver.c +++ b/dlls/rpcrt4/ndr_clientserver.c @@ -67,8 +67,9 @@ void WINAPI NdrClientInitializeNew( PRPC_MESSAGE pRpcMessage, PMIDL_STUB_MESSAGE pStubMsg->pPointerQueueState = NULL; pStubMsg->IgnoreEmbeddedPointers = 0; pStubMsg->PointerBufferMark = NULL; - pStubMsg->fBufferValid = 0; + pStubMsg->CorrDespIncrement = 0; pStubMsg->uFlags = 0; + pStubMsg->UniquePtrCount = 0; pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; pStubMsg->pfnFree = pStubDesc->pfnFree; pStubMsg->StackTop = NULL; @@ -81,6 +82,13 @@ void WINAPI NdrClientInitializeNew( PRPC_MESSAGE pRpcMessage, PMIDL_STUB_MESSAGE pStubMsg->fHasReturn = 0; pStubMsg->fHasExtensions = 0; pStubMsg->fHasNewCorrDesc = 0; + pStubMsg->fIsIn = 0; + pStubMsg->fIsOut = 0; + pStubMsg->fIsOicf = 0; + pStubMsg->fBufferValid = 0; + pStubMsg->fHasMemoryValidateCallback = 0; + pStubMsg->fInFree = 0; + pStubMsg->fNeedMCCP = 0; pStubMsg->fUnused = 0; pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE; pStubMsg->pvDestContext = NULL; @@ -113,6 +121,7 @@ unsigned char* WINAPI NdrServerInitializeNew( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_M pStubMsg->IgnoreEmbeddedPointers = 0; pStubMsg->PointerBufferMark = NULL; pStubMsg->uFlags = 0; + pStubMsg->UniquePtrCount = 0; pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; pStubMsg->pfnFree = pStubDesc->pfnFree; pStubMsg->StackTop = NULL; @@ -126,6 +135,12 @@ unsigned char* WINAPI NdrServerInitializeNew( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_M pStubMsg->fHasReturn = 0; pStubMsg->fHasExtensions = 0; pStubMsg->fHasNewCorrDesc = 0; + pStubMsg->fIsIn = 0; + pStubMsg->fIsOut = 0; + pStubMsg->fIsOicf = 0; + pStubMsg->fHasMemoryValidateCallback = 0; + pStubMsg->fInFree = 0; + pStubMsg->fNeedMCCP = 0; pStubMsg->fUnused = 0; pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE; pStubMsg->pvDestContext = NULL; diff --git a/dlls/rpcrt4/ndr_marshall.c b/dlls/rpcrt4/ndr_marshall.c index bdc50986224..4e7643ac625 100644 --- a/dlls/rpcrt4/ndr_marshall.c +++ b/dlls/rpcrt4/ndr_marshall.c @@ -110,6 +110,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \ } while (0) +#define NDR_POINTER_ID_BASE 0x20000 +#define NDR_POINTER_ID(pStubMsg) (NDR_POINTER_ID_BASE + ((pStubMsg)->UniquePtrCount++) * 4) #define NDR_TABLE_SIZE 128 #define NDR_TABLE_MASK 127 @@ -688,6 +690,37 @@ static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void * pStubMsg->Buffer += size; } +/* verify that string data sitting in the buffer is valid and safe to + * unmarshall */ +static void validate_string_data(MIDL_STUB_MESSAGE *pStubMsg, ULONG bufsize, ULONG esize) +{ + ULONG i; + + /* verify the buffer is safe to access */ + if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || + (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) + { + ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, + pStubMsg->BufferEnd, pStubMsg->Buffer); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + /* strings must always have null terminating bytes */ + if (bufsize < esize) + { + ERR("invalid string length of %d\n", bufsize / esize); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + for (i = bufsize - esize; i < bufsize; i++) + if (pStubMsg->Buffer[i] != 0) + { + ERR("string not null-terminated at byte position %d, data is 0x%x\n", + i, pStubMsg->Buffer[i]); + RpcRaiseException(RPC_S_INVALID_BOUND); + } +} + /* * NdrConformantString: * @@ -789,7 +822,7 @@ void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat ) { - ULONG bufsize, memsize, esize, i; + ULONG bufsize, memsize, esize; TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); @@ -819,29 +852,7 @@ ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, memsize = safe_multiply(esize, pStubMsg->MaxCount); bufsize = safe_multiply(esize, pStubMsg->ActualCount); - /* strings must always have null terminating bytes */ - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - - /* verify the buffer is safe to access */ - if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || - (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) - { - ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, - pStubMsg->BufferEnd, pStubMsg->Buffer); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - } + validate_string_data(pStubMsg, bufsize, esize); safe_buffer_increment(pStubMsg, bufsize); pStubMsg->MemorySize += memsize; @@ -855,7 +866,7 @@ ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) { - ULONG bufsize, memsize, esize, i; + ULONG bufsize, memsize, esize; TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", pStubMsg, *ppMemory, pFormat, fMustAlloc); @@ -890,32 +901,7 @@ unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg memsize = safe_multiply(esize, pStubMsg->MaxCount); bufsize = safe_multiply(esize, pStubMsg->ActualCount); - /* strings must always have null terminating bytes */ - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - /* verify the buffer is safe to access */ - if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || - (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) - { - ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, - pStubMsg->BufferEnd, pStubMsg->Buffer); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return NULL; - } - - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } + validate_string_data(pStubMsg, bufsize, esize); if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, memsize); @@ -1000,7 +986,7 @@ unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStu PFORMAT_STRING pFormat, unsigned char fMustAlloc) { - ULONG bufsize, memsize, esize, i, maxsize; + ULONG bufsize, memsize, esize, maxsize; TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", pStubMsg, *ppMemory, pFormat, fMustAlloc); @@ -1025,31 +1011,7 @@ unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStu memsize = esize * maxsize; bufsize = safe_multiply(esize, pStubMsg->ActualCount); - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - /* verify the buffer is safe to access */ - if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || - (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) - { - ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, - pStubMsg->BufferEnd, pStubMsg->Buffer); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return NULL; - } - - /* strings must always have null terminating bytes */ - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - } + validate_string_data(pStubMsg, bufsize, esize); if (fMustAlloc || !*ppMemory) *ppMemory = NdrAllocate(pStubMsg, memsize); @@ -1116,7 +1078,7 @@ void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { - ULONG bufsize, memsize, esize, i, maxsize; + ULONG bufsize, memsize, esize, maxsize; TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); @@ -1141,29 +1103,7 @@ ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, memsize = esize * maxsize; bufsize = safe_multiply(esize, pStubMsg->ActualCount); - /* strings must always have null terminating bytes */ - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - - /* verify the buffer is safe to access */ - if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || - (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) - { - ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, - pStubMsg->BufferEnd, pStubMsg->Buffer); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - } + validate_string_data(pStubMsg, bufsize, esize); safe_buffer_increment(pStubMsg, bufsize); pStubMsg->MemorySize += memsize; @@ -1221,7 +1161,7 @@ static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, pointer_needs_marshaling = 1; else pointer_needs_marshaling = 0; - pointer_id = (ULONG)Pointer; + pointer_id = Pointer ? NDR_POINTER_ID(pStubMsg) : 0; TRACE("writing 0x%08x to buffer\n", pointer_id); NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); break; @@ -1622,7 +1562,7 @@ static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, * EmbeddedPointerUnmarshall */ static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pDstMemoryPtrs, + unsigned char *pDstBuffer, unsigned char *pSrcMemoryPtrs, PFORMAT_STRING pFormat, unsigned char fMustAlloc) @@ -1632,7 +1572,7 @@ static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned i; unsigned char *saved_buffer = NULL; - TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstMemoryPtrs, pSrcMemoryPtrs, pFormat, fMustAlloc); + TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstBuffer, pSrcMemoryPtrs, pFormat, fMustAlloc); if (*pFormat != RPC_FC_PP) return NULL; pFormat += 2; @@ -1670,16 +1610,16 @@ static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, } for (i = 0; i < rep; i++) { PFORMAT_STRING info = pFormat; - unsigned char *memdstbase = pDstMemoryPtrs + (i * stride); + unsigned char *bufdstbase = pDstBuffer + (i * stride); unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride); unsigned char *bufbase = Mark + (i * stride); unsigned u; for (u=0; uBufferMark = pStubMsg->Buffer; - safe_copy_from_buffer(pStubMsg, *ppMemory, pCVStructFormat->memory_size); + /* mark the start of the constant data */ + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size); pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); @@ -4307,35 +4248,25 @@ unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE if ((cvarray_type == RPC_FC_C_CSTRING) || (cvarray_type == RPC_FC_C_WSTRING)) - { - ULONG i; - /* strings must always have null terminating bytes */ - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - } + validate_string_data(pStubMsg, bufsize, esize); + + /* mark the start of the array data */ + saved_array_buffer = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, bufsize); + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + /* copy the constant data */ + memcpy(*ppMemory, saved_buffer, pCVStructFormat->memory_size); /* copy the array data */ - safe_copy_from_buffer(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize); + TRACE("copying %p to %p\n", saved_array_buffer, *ppMemory + pCVStructFormat->memory_size); + memcpy(*ppMemory + pCVStructFormat->memory_size, saved_array_buffer, bufsize); if (cvarray_type == RPC_FC_C_CSTRING) TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size))); else if (cvarray_type == RPC_FC_C_WSTRING) TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size))); - EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */); - return NULL; } diff --git a/dlls/rpcrt4/rpc_binding.c b/dlls/rpcrt4/rpc_binding.c index 500e5f80f6c..e42b8f9d676 100644 --- a/dlls/rpcrt4/rpc_binding.c +++ b/dlls/rpcrt4/rpc_binding.c @@ -820,6 +820,17 @@ RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WS } /*********************************************************************** + * I_RpcBindingInqTransportType (RPCRT4.@) + */ +RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsigned int * Type ) +{ + + FIXME( "(%p,%p): stub\n", Binding, Type); + *Type = TRANSPORT_TYPE_LPC; + return RPC_S_OK; +} + +/*********************************************************************** * I_RpcBindingSetAsync (RPCRT4.@) * NOTES * Exists in win9x and winNT, but with different number of arguments @@ -1404,7 +1415,8 @@ RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, return RPC_S_UNKNOWN_AUTHN_LEVEL; } - if (AuthzSvr) + /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */ + if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT) { FIXME("unsupported AuthzSvr %u\n", AuthzSvr); return RPC_S_UNKNOWN_AUTHZ_SERVICE; @@ -1533,7 +1545,8 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, return RPC_S_UNKNOWN_AUTHN_LEVEL; } - if (AuthzSvr) + /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */ + if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT) { FIXME("unsupported AuthzSvr %u\n", AuthzSvr); return RPC_S_UNKNOWN_AUTHZ_SERVICE; @@ -1542,7 +1555,7 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, r = EnumerateSecurityPackagesW(&package_count, &packages); if (r != SEC_E_OK) { - ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r); + ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", r); return RPC_S_SEC_PKG_ERROR; } @@ -1587,7 +1600,7 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, } else { - ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r); + ERR("AcquireCredentialsHandleW failed with error 0x%08x\n", r); return RPC_S_SEC_PKG_ERROR; } } diff --git a/dlls/rpcrt4/rpc_binding.h b/dlls/rpcrt4/rpc_binding.h index 3251df210c7..2838037ad58 100644 --- a/dlls/rpcrt4/rpc_binding.h +++ b/dlls/rpcrt4/rpc_binding.h @@ -150,9 +150,6 @@ RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding); RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RPC_SYNTAX_IDENTIFIER *InterfaceId); RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection); -BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply); -HANDLE RPCRT4_GetMasterMutex(void); -HANDLE RPCRT4_RpcssNPConnect(void); static inline const char *rpcrt4_conn_get_name(const RpcConnection *Connection) { diff --git a/dlls/rpcrt4/rpc_epmap.c b/dlls/rpcrt4/rpc_epmap.c index 46244ec36e0..074217e72c9 100644 --- a/dlls/rpcrt4/rpc_epmap.c +++ b/dlls/rpcrt4/rpc_epmap.c @@ -3,6 +3,7 @@ * * Copyright 2002 Greg Turner * Copyright 2001 Ove Kåven, TransGaming Technologies + * 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 @@ -17,14 +18,9 @@ * 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 - * - * TODO: - * - actually do things right */ #include -#include -#include #include "windef.h" #include "winbase.h" @@ -33,8 +29,10 @@ #include "rpc.h" #include "wine/debug.h" +#include "wine/exception.h" #include "rpc_binding.h" +#include "epm.h" #include "epm_towers.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); @@ -43,8 +41,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); * * ncadg_ip_udp: 135 * ncacn_ip_tcp: 135 - * ncacn_np: \\pipe\epmapper (?) + * ncacn_np: \\pipe\epmapper * ncalrpc: epmapper + * ncacn_http: 593 * * If the user's machine ran a DCE RPC daemon, it would * probably be possible to connect to it, but there are many @@ -63,77 +62,210 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); * of running a fully functional DCOM server using Wine... */ +static const struct epm_endpoints +{ + const char *protseq; + const char *endpoint; +} epm_endpoints[] = +{ + { "ncacn_np", "\\pipe\\epmapper" }, + { "ncacn_ip_tcp", "135" }, + { "ncacn_ip_udp", "135" }, + { "ncalprc", "epmapper" }, + { "ncacn_http", "593" }, +}; + +static BOOL start_rpcss(void) +{ + PROCESS_INFORMATION pi; + STARTUPINFOW si; + static WCHAR cmd[6]; + static const WCHAR rpcss[] = {'r','p','c','s','s',0}; + BOOL rslt; + + TRACE("\n"); + + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + ZeroMemory(&si, sizeof(STARTUPINFOA)); + si.cb = sizeof(STARTUPINFOA); + + memcpy(cmd, rpcss, sizeof(rpcss)); + + rslt = CreateProcessW( + NULL, /* executable */ + cmd, /* command line */ + NULL, /* process security attributes */ + NULL, /* primary thread security attributes */ + FALSE, /* inherit handles */ + 0, /* creation flags */ + NULL, /* use parent's environment */ + NULL, /* use parent's current directory */ + &si, /* STARTUPINFO pointer */ + &pi /* PROCESS_INFORMATION */ + ); + + if (rslt) + { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + Sleep(100); + } + + return rslt; +} + +static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_HANDLE *epm_handle) +{ + RpcBinding *bind = (RpcBinding *)handle; + const char * pszEndpoint = NULL; + RPC_STATUS status; + RpcBinding* epm_bind; + unsigned int i; + + if (bind->server) + return RPC_S_INVALID_BINDING; + + for (i = 0; i < sizeof(epm_endpoints)/sizeof(epm_endpoints[0]); i++) + if (!strcmp(bind->Protseq, epm_endpoints[i].protseq)) + pszEndpoint = epm_endpoints[i].endpoint; + + if (!pszEndpoint) + { + FIXME("no endpoint for the endpoint-mapper found for protseq %s\n", debugstr_a(bind->Protseq)); + return RPC_S_PROTSEQ_NOT_SUPPORTED; + } + + status = RpcBindingCopy(handle, epm_handle); + if (status != RPC_S_OK) return status; + + epm_bind = (RpcBinding*)*epm_handle; + if (epm_bind->AuthInfo) + { + /* don't bother with authenticating against the EPM by default + * (see EnableAuthEpResolution registry value) */ + RpcAuthInfo_Release(epm_bind->AuthInfo); + epm_bind->AuthInfo = NULL; + } + RPCRT4_ResolveBinding(epm_bind, pszEndpoint); + TRACE("RPC_S_OK\n"); + return RPC_S_OK; +} + +static RPC_STATUS get_epm_handle_server(RPC_BINDING_HANDLE *epm_handle) +{ + unsigned char string_binding[] = "ncacn_np:.[\\pipe\\epmapper]"; + + return RpcBindingFromStringBindingA(string_binding, epm_handle); +} + +static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *__eptr) +{ + switch (GetExceptionCode()) + { + case EXCEPTION_ACCESS_VIOLATION: + case EXCEPTION_ILLEGAL_INSTRUCTION: + return EXCEPTION_CONTINUE_SEARCH; + default: + return EXCEPTION_EXECUTE_HANDLER; + } +} + /*********************************************************************** * RpcEpRegisterA (RPCRT4.@) */ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, UUID_VECTOR *UuidVector, RPC_CSTR Annotation ) { - RPCSS_NP_MESSAGE msg; - RPCSS_NP_REPLY reply; - char *vardata_payload, *vp; PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; - unsigned long c; - RPC_STATUS rslt = RPC_S_OK; + unsigned long i; + RPC_STATUS status = RPC_S_OK; + error_status_t status2; + ept_entry_t *entries; + handle_t handle; TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation)); TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); - for (c=0; cCount; c++) { - RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]); - TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq)); - TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint)); + for (i=0; iCount; i++) { + RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); + TRACE(" protseq[%ld]=%s\n", i, debugstr_a(bind->Protseq)); + TRACE(" endpoint[%ld]=%s\n", i, debugstr_a(bind->Endpoint)); } if (UuidVector) { - for (c=0; cCount; c++) - TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c])); + for (i=0; iCount; i++) + TRACE(" obj[%ld]=%s\n", i, debugstr_guid(UuidVector->Uuid[i])); } - /* FIXME: Do something with annotation. */ + if (!BindingVector->Count) return RPC_S_OK; - /* construct the message to rpcss */ - msg.message_type = RPCSS_NP_MESSAGE_TYPEID_REGISTEREPMSG; - msg.message.registerepmsg.iface = If->InterfaceId; - msg.message.registerepmsg.no_replace = 0; + entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entries) * BindingVector->Count * (UuidVector ? UuidVector->Count : 1)); + if (!entries) + return RPC_S_OUT_OF_MEMORY; - msg.message.registerepmsg.object_count = (UuidVector) ? UuidVector->Count : 0; - msg.message.registerepmsg.binding_count = BindingVector->Count; - - /* calculate vardata payload size */ - msg.vardata_payload_size = msg.message.registerepmsg.object_count * sizeof(UUID); - for (c=0; c < msg.message.registerepmsg.binding_count; c++) { - RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]); - msg.vardata_payload_size += strlen(bind->Protseq) + 1; - msg.vardata_payload_size += strlen(bind->Endpoint) + 1; + status = get_epm_handle_server(&handle); + if (status != RPC_S_OK) + { + HeapFree(GetProcessHeap(), 0, entries); + return status; } - /* allocate the payload buffer */ - vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size); - if (!vardata_payload) - return RPC_S_OUT_OF_MEMORY; - - /* populate the payload data */ - for (c=0; c < msg.message.registerepmsg.object_count; c++) { - CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID)); - vp += sizeof(UUID); + for (i = 0; i < BindingVector->Count; i++) + { + unsigned j; + RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); + for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) + { + int len = strlen((char *)Annotation); + status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, + bind->Protseq, bind->Endpoint, + bind->NetworkAddr, + &entries[i*(UuidVector ? UuidVector->Count : 1) + j].tower); + if (status != RPC_S_OK) break; + + if (UuidVector) + memcpy(&entries[i * UuidVector->Count].object, &UuidVector->Uuid[j], sizeof(GUID)); + else + memset(&entries[i].object, 0, sizeof(entries[i].object)); + memcpy(entries[i].annotation, Annotation, min(len + 1, ept_max_annotation_size)); + } } - for (c=0; c < msg.message.registerepmsg.binding_count; c++) { - RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]); - unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1; - CopyMemory(vp, bind->Protseq, pslen); - vp += pslen; - CopyMemory(vp, bind->Endpoint, eplen); - vp += eplen; + if (status == RPC_S_OK) + { + while (TRUE) + { + __TRY + { + ept_insert(handle, BindingVector->Count * (UuidVector ? UuidVector->Count : 1), + entries, TRUE, &status2); + } + __EXCEPT(rpc_filter) + { + status2 = GetExceptionCode(); + } + __ENDTRY + if (status2 == RPC_S_SERVER_UNAVAILABLE) + { + if (start_rpcss()) + continue; + } + if (status2 != RPC_S_OK) + ERR("ept_insert failed with error %d\n", status2); + status = status2; /* FIXME: convert status? */ + break; + } } + RpcBindingFree(&handle); - /* send our request */ - if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply)) - rslt = RPC_S_OUT_OF_MEMORY; + for (i = 0; i < BindingVector->Count; i++) + { + unsigned j; + for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) + I_RpcFree(entries[i*(UuidVector ? UuidVector->Count : 1) + j].tower); + } - /* free the payload buffer */ - LocalFree(vardata_payload); + HeapFree(GetProcessHeap(), 0, entries); - return rslt; + return status; } /*********************************************************************** @@ -142,68 +274,85 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, UUID_VECTOR *UuidVector ) { - RPCSS_NP_MESSAGE msg; - RPCSS_NP_REPLY reply; - char *vardata_payload, *vp; PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; - unsigned long c; - RPC_STATUS rslt = RPC_S_OK; + unsigned long i; + RPC_STATUS status = RPC_S_OK; + error_status_t status2; + ept_entry_t *entries; + handle_t handle; TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector); TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); - for (c=0; cCount; c++) { - RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]); - TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq)); - TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint)); + for (i=0; iCount; i++) { + RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); + TRACE(" protseq[%ld]=%s\n", i, debugstr_a(bind->Protseq)); + TRACE(" endpoint[%ld]=%s\n", i, debugstr_a(bind->Endpoint)); } if (UuidVector) { - for (c=0; cCount; c++) - TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c])); + for (i=0; iCount; i++) + TRACE(" obj[%ld]=%s\n", i, debugstr_guid(UuidVector->Uuid[i])); } - /* construct the message to rpcss */ - msg.message_type = RPCSS_NP_MESSAGE_TYPEID_UNREGISTEREPMSG; - msg.message.unregisterepmsg.iface = If->InterfaceId; - - msg.message.unregisterepmsg.object_count = (UuidVector) ? UuidVector->Count : 0; - msg.message.unregisterepmsg.binding_count = BindingVector->Count; + entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entries) * BindingVector->Count * (UuidVector ? UuidVector->Count : 1)); + if (!entries) + return RPC_S_OUT_OF_MEMORY; - /* calculate vardata payload size */ - msg.vardata_payload_size = msg.message.unregisterepmsg.object_count * sizeof(UUID); - for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) { - RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]); - msg.vardata_payload_size += strlen(bind->Protseq) + 1; - msg.vardata_payload_size += strlen(bind->Endpoint) + 1; + status = get_epm_handle_server(&handle); + if (status != RPC_S_OK) + { + HeapFree(GetProcessHeap(), 0, entries); + return status; } - /* allocate the payload buffer */ - vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size); - if (!vardata_payload) - return RPC_S_OUT_OF_MEMORY; - - /* populate the payload data */ - for (c=0; c < msg.message.unregisterepmsg.object_count; c++) { - CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID)); - vp += sizeof(UUID); + for (i = 0; i < BindingVector->Count; i++) + { + unsigned j; + RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); + for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) + { + status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, + bind->Protseq, bind->Endpoint, + bind->NetworkAddr, + &entries[i*(UuidVector ? UuidVector->Count : 1) + j].tower); + if (status != RPC_S_OK) break; + + if (UuidVector) + memcpy(&entries[i * UuidVector->Count + j].object, &UuidVector->Uuid[j], sizeof(GUID)); + else + memset(&entries[i].object, 0, sizeof(entries[i].object)); + } } - for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) { - RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]); - unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1; - CopyMemory(vp, bind->Protseq, pslen); - vp += pslen; - CopyMemory(vp, bind->Endpoint, eplen); - vp += eplen; + if (status == RPC_S_OK) + { + __TRY + { + ept_insert(handle, BindingVector->Count * (UuidVector ? UuidVector->Count : 1), + entries, TRUE, &status2); + } + __EXCEPT(rpc_filter) + { + status2 = GetExceptionCode(); + } + __ENDTRY + if (status2 == RPC_S_SERVER_UNAVAILABLE) + status2 = EPT_S_NOT_REGISTERED; + if (status2 != RPC_S_OK) + ERR("ept_insert failed with error %d\n", status2); + status = status2; /* FIXME: convert status? */ } + RpcBindingFree(&handle); - /* send our request */ - if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply)) - rslt = RPC_S_OUT_OF_MEMORY; + for (i = 0; i < BindingVector->Count; i++) + { + unsigned j; + for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) + I_RpcFree(entries[i*(UuidVector ? UuidVector->Count : 1) + j].tower); + } - /* free the payload buffer */ - LocalFree(vardata_payload); + HeapFree(GetProcessHeap(), 0, entries); - return rslt; + return status; } /*********************************************************************** @@ -211,51 +360,93 @@ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bin */ RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec ) { - RPCSS_NP_MESSAGE msg; - RPCSS_NP_REPLY reply; PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec; RpcBinding* bind = (RpcBinding*)Binding; + RPC_STATUS status; + error_status_t status2; + handle_t handle; + ept_lookup_handle_t entry_handle = NULL; + twr_t *tower; + twr_t *towers[4] = { NULL }; + unsigned32 num_towers, i; + GUID uuid = GUID_NULL; + char *resolved_endpoint = NULL; TRACE("(%p,%p)\n", Binding, IfSpec); TRACE(" protseq=%s\n", debugstr_a(bind->Protseq)); TRACE(" obj=%s\n", debugstr_guid(&bind->ObjectUuid)); + TRACE(" networkaddr=%s\n", debugstr_a(bind->NetworkAddr)); TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); - /* FIXME: totally untested */ - /* just return for fully bound handles */ if (bind->Endpoint && (bind->Endpoint[0] != '\0')) return RPC_S_OK; - /* construct the message to rpcss */ - msg.message_type = RPCSS_NP_MESSAGE_TYPEID_RESOLVEEPMSG; - msg.message.resolveepmsg.iface = If->InterfaceId; - msg.message.resolveepmsg.object = bind->ObjectUuid; - - msg.vardata_payload_size = strlen(bind->Protseq) + 1; + status = get_epm_handle_client(Binding, &handle); + if (status != RPC_S_OK) return status; + + status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, bind->Protseq, + ((RpcBinding *)handle)->Endpoint, + bind->NetworkAddr, &tower); + if (status != RPC_S_OK) + { + WARN("couldn't get tower\n"); + RpcBindingFree(&handle); + return status; + } - /* send the message */ - if (!RPCRT4_RPCSSOnDemandCall(&msg, bind->Protseq, &reply)) - return RPC_S_OUT_OF_MEMORY; + while (TRUE) + { + __TRY + { + ept_map(handle, &uuid, tower, &entry_handle, sizeof(towers)/sizeof(towers[0]), &num_towers, towers, &status2); + /* FIXME: translate status2? */ + } + __EXCEPT(rpc_filter) + { + status2 = GetExceptionCode(); + } + __ENDTRY + if (status2 == RPC_S_SERVER_UNAVAILABLE) + { + if (start_rpcss()) + continue; + } + break; + }; - /* empty-string result means not registered */ - if (reply.as_string[0] == '\0') - return EPT_S_NOT_REGISTERED; - - /* otherwise we fully bind the handle & return RPC_S_OK */ - return RPCRT4_ResolveBinding(Binding, reply.as_string); -} + RpcBindingFree(&handle); + I_RpcFree(tower); -typedef unsigned int unsigned32; -typedef struct twr_t + if (status2 != RPC_S_OK) + { + ERR("ept_map failed for ifid %s, protseq %s, networkaddr %s\n", debugstr_guid(&If->TransferSyntax.SyntaxGUID), bind->Protseq, bind->NetworkAddr); + return status2; + } + + for (i = 0; i < num_towers; i++) + { + /* only parse the tower if we haven't already found a suitable + * endpoint, otherwise just free the tower */ + if (!resolved_endpoint) { - unsigned32 tower_length; - /* [size_is] */ BYTE tower_octet_string[ 1 ]; - } twr_t; + status = TowerExplode(towers[i], NULL, NULL, NULL, &resolved_endpoint, NULL); + TRACE("status = %ld\n", status); + } + I_RpcFree(towers[i]); + } + + if (resolved_endpoint) + { + RPCRT4_ResolveBinding(Binding, resolved_endpoint); + I_RpcFree(resolved_endpoint); + return RPC_S_OK; + } + + WARN("couldn't find an endpoint\n"); + return EPT_S_NOT_REGISTERED; +} -/*********************************************************************** - * TowerExplode (RPCRT4.@) - */ RPC_STATUS WINAPI TowerExplode( const twr_t *tower, PRPC_SYNTAX_IDENTIFIER object, PRPC_SYNTAX_IDENTIFIER syntax, char **protseq, char **endpoint, char **address) @@ -388,3 +579,13 @@ RPC_STATUS WINAPI TowerConstruct( } return RPC_S_OK; } + +void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len) +{ + return HeapAlloc(GetProcessHeap(), 0, len); +} + +void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr) +{ + HeapFree(GetProcessHeap(), 0, ptr); +} diff --git a/dlls/rpcrt4/rpcrt4.spec b/dlls/rpcrt4/rpcrt4.spec index bbf5a013299..95f13d8d397 100644 --- a/dlls/rpcrt4/rpcrt4.spec +++ b/dlls/rpcrt4/rpcrt4.spec @@ -31,7 +31,7 @@ @ stub I_RpcBindingInqDynamicEndPointW @ stub I_RpcBindingInqLocalClientPID # wxp @ stub I_RpcBindingInqSecurityContext -@ stub I_RpcBindingInqTransportType +@ stdcall I_RpcBindingInqTransportType(ptr ptr) @ stub I_RpcBindingInqWireIdForSnego @ stub I_RpcBindingIsClientLocal # 9x version of I_RpcBindingSetAsync has 3 arguments, not 2 diff --git a/dlls/rpcrt4/rpcrt4_main.c b/dlls/rpcrt4/rpcrt4_main.c index 8e565afdfc4..f70892cd6e9 100644 --- a/dlls/rpcrt4/rpcrt4_main.c +++ b/dlls/rpcrt4/rpcrt4_main.c @@ -53,19 +53,12 @@ #include "rpcproxy.h" #include "rpc_binding.h" -#include "rpcss_np_client.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(rpc); static UUID uuid_nil; -static HANDLE master_mutex; - -HANDLE RPCRT4_GetMasterMutex(void) -{ - return master_mutex; -} static CRITICAL_SECTION uuid_cs; static CRITICAL_SECTION_DEBUG critsect_debug = @@ -122,9 +115,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) switch (fdwReason) { case DLL_PROCESS_ATTACH: - master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME); - if (!master_mutex) - ERR("Failed to create master mutex\n"); break; case DLL_THREAD_DETACH: @@ -145,8 +135,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) break; case DLL_PROCESS_DETACH: - CloseHandle(master_mutex); - master_mutex = NULL; break; } @@ -645,102 +633,6 @@ HRESULT WINAPI DllRegisterServer( void ) return S_OK; } -static BOOL RPCRT4_StartRPCSS(void) -{ - PROCESS_INFORMATION pi; - STARTUPINFOA si; - static char cmd[6]; - BOOL rslt; - - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); - ZeroMemory(&si, sizeof(STARTUPINFOA)); - si.cb = sizeof(STARTUPINFOA); - - /* apparently it's not OK to use a constant string below */ - CopyMemory(cmd, "rpcss", 6); - - /* FIXME: will this do the right thing when run as a test? */ - rslt = CreateProcessA( - NULL, /* executable */ - cmd, /* command line */ - NULL, /* process security attributes */ - NULL, /* primary thread security attributes */ - FALSE, /* inherit handles */ - 0, /* creation flags */ - NULL, /* use parent's environment */ - NULL, /* use parent's current directory */ - &si, /* STARTUPINFO pointer */ - &pi /* PROCESS_INFORMATION */ - ); - - if (rslt) { - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } - - return rslt; -} - -/*********************************************************************** - * RPCRT4_RPCSSOnDemandCall (internal) - * - * Attempts to send a message to the RPCSS process - * on the local machine, invoking it if necessary. - * For remote RPCSS calls, use.... your imagination. - * - * PARAMS - * msg [I] pointer to the RPCSS message - * vardata_payload [I] pointer vardata portion of the RPCSS message - * reply [O] pointer to reply structure - * - * RETURNS - * TRUE if successful - * FALSE otherwise - */ -BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply) -{ - HANDLE client_handle; - BOOL ret; - int i, j = 0; - - TRACE("(msg == %p, vardata_payload == %p, reply == %p)\n", msg, vardata_payload, reply); - - client_handle = RPCRT4_RpcssNPConnect(); - - while (INVALID_HANDLE_VALUE == client_handle) { - /* start the RPCSS process */ - if (!RPCRT4_StartRPCSS()) { - ERR("Unable to start RPCSS process.\n"); - return FALSE; - } - /* wait for a connection (w/ periodic polling) */ - for (i = 0; i < 60; i++) { - Sleep(200); - client_handle = RPCRT4_RpcssNPConnect(); - if (INVALID_HANDLE_VALUE != client_handle) break; - } - /* we are only willing to try twice */ - if (j++ >= 1) break; - } - - if (INVALID_HANDLE_VALUE == client_handle) { - /* no dice! */ - ERR("Unable to connect to RPCSS process!\n"); - SetLastError(RPC_E_SERVER_DIED_DNE); - return FALSE; - } - - /* great, we're connected. now send the message */ - ret = TRUE; - if (!RPCRT4_SendReceiveNPMsg(client_handle, msg, vardata_payload, reply)) { - ERR("Something is amiss: RPC_SendReceive failed.\n"); - ret = FALSE; - } - CloseHandle(client_handle); - - return ret; -} - #define MAX_RPC_ERROR_TEXT 256 /****************************************************************************** diff --git a/dlls/rpcrt4/rpcss_np_client.c b/dlls/rpcrt4/rpcss_np_client.c deleted file mode 100644 index 016f77f5f15..00000000000 --- a/dlls/rpcrt4/rpcss_np_client.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * RPCSS named pipe client implementation - * - * Copyright (C) 2002 Greg Turner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wine/rpcss_shared.h" -#include "wine/debug.h" - -#include "rpc_binding.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -HANDLE RPCRT4_RpcssNPConnect(void) -{ - HANDLE the_pipe; - DWORD dwmode, wait_result; - HANDLE master_mutex = RPCRT4_GetMasterMutex(); - - TRACE("\n"); - - while (TRUE) { - - wait_result = WaitForSingleObject(master_mutex, MASTER_MUTEX_TIMEOUT); - switch (wait_result) { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: - break; - case WAIT_FAILED: - case WAIT_TIMEOUT: - default: - ERR("This should never happen: couldn't enter mutex.\n"); - return NULL; - } - - /* try to open the client side of the named pipe. */ - the_pipe = CreateFileA( - NAME_RPCSS_NAMED_PIPE, /* pipe name */ - GENERIC_READ | GENERIC_WRITE, /* r/w access */ - 0, /* no sharing */ - NULL, /* no security attributes */ - OPEN_EXISTING, /* open an existing pipe */ - 0, /* default attributes */ - NULL /* no template file */ - ); - - if (the_pipe != INVALID_HANDLE_VALUE) - break; - - if (GetLastError() != ERROR_PIPE_BUSY) { - WARN("Unable to open named pipe %s (assuming unavailable).\n", - debugstr_a(NAME_RPCSS_NAMED_PIPE)); - break; - } - - WARN("Named pipe busy (will wait)\n"); - - if (!ReleaseMutex(master_mutex)) - ERR("Failed to release master mutex. Expect deadlock.\n"); - - /* wait for the named pipe. We are only willing to wait for 5 seconds. - It should be available /very/ soon. */ - if (! WaitNamedPipeA(NAME_RPCSS_NAMED_PIPE, MASTER_MUTEX_WAITNAMEDPIPE_TIMEOUT)) - { - ERR("Named pipe unavailable after waiting. Something is probably wrong.\n"); - break; - } - - } - - if (the_pipe != INVALID_HANDLE_VALUE) { - dwmode = PIPE_READMODE_MESSAGE; - /* SetNamedPipeHandleState not implemented ATM, but still seems to work somehow. */ - if (! SetNamedPipeHandleState(the_pipe, &dwmode, NULL, NULL)) - WARN("Failed to set pipe handle state\n"); - } - - if (!ReleaseMutex(master_mutex)) - ERR("Uh oh, failed to leave the RPC Master Mutex!\n"); - - return the_pipe; -} - -BOOL RPCRT4_SendReceiveNPMsg(HANDLE np, PRPCSS_NP_MESSAGE msg, char *vardata, PRPCSS_NP_REPLY reply) -{ - DWORD count; - UINT32 payload_offset; - RPCSS_NP_MESSAGE vardata_payload_msg; - - TRACE("(np == %p, msg == %p, vardata == %p, reply == %p)\n", - np, msg, vardata, reply); - - if (! WriteFile(np, msg, sizeof(RPCSS_NP_MESSAGE), &count, NULL)) { - ERR("write failed.\n"); - return FALSE; - } - - if (count != sizeof(RPCSS_NP_MESSAGE)) { - ERR("write count mismatch.\n"); - return FALSE; - } - - /* process the vardata payload if necessary */ - vardata_payload_msg.message_type = RPCSS_NP_MESSAGE_TYPEID_VARDATAPAYLOADMSG; - vardata_payload_msg.vardata_payload_size = 0; /* meaningless */ - for ( payload_offset = 0; payload_offset < msg->vardata_payload_size; - payload_offset += VARDATA_PAYLOAD_BYTES ) { - TRACE("sending vardata payload. vd=%p, po=%d, ps=%d\n", vardata, - payload_offset, msg->vardata_payload_size); - ZeroMemory(vardata_payload_msg.message.vardatapayloadmsg.payload, VARDATA_PAYLOAD_BYTES); - CopyMemory(vardata_payload_msg.message.vardatapayloadmsg.payload, - vardata, - min( VARDATA_PAYLOAD_BYTES, msg->vardata_payload_size - payload_offset )); - vardata += VARDATA_PAYLOAD_BYTES; - if (! WriteFile(np, &vardata_payload_msg, sizeof(RPCSS_NP_MESSAGE), &count, NULL)) { - ERR("vardata write failed at %u bytes.\n", payload_offset); - return FALSE; - } - } - - if (! ReadFile(np, reply, sizeof(RPCSS_NP_REPLY), &count, NULL)) { - ERR("read failed.\n"); - return FALSE; - } - - if (count != sizeof(RPCSS_NP_REPLY)) { - ERR("read count mismatch. got %d.\n", count); - return FALSE; - } - - /* message execution was successful */ - return TRUE; -} diff --git a/dlls/rpcrt4/tests/generated.c b/dlls/rpcrt4/tests/generated.c index 9c4a5a778a0..609e49cbf25 100644 --- a/dlls/rpcrt4/tests/generated.c +++ b/dlls/rpcrt4/tests/generated.c @@ -412,7 +412,7 @@ static void test_pack_MIDL_STUB_MESSAGE(void) TEST_FIELD(MIDL_STUB_MESSAGE, struct NDR_POINTER_QUEUE_STATE *, pPointerQueueState, 44, 4, 4); TEST_FIELD(MIDL_STUB_MESSAGE, int, IgnoreEmbeddedPointers, 48, 4, 4); TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char *, PointerBufferMark, 52, 4, 4); - TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char, fBufferValid, 56, 1, 1); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char, CorrDespIncrement, 56, 1, 1); TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char, uFlags, 57, 1, 1); TEST_FIELD(MIDL_STUB_MESSAGE, ULONG_PTR, MaxCount, 60, 4, 4); TEST_FIELD(MIDL_STUB_MESSAGE, ULONG, Offset, 64, 4, 4); diff --git a/dlls/rpcrt4/tests/ndr_marshall.c b/dlls/rpcrt4/tests/ndr_marshall.c index ecb9f57f625..a860253ed5a 100644 --- a/dlls/rpcrt4/tests/ndr_marshall.c +++ b/dlls/rpcrt4/tests/ndr_marshall.c @@ -1164,7 +1164,7 @@ static void test_client_init(void) TEST_ZERO(pPointerQueueState, "%p"); TEST_ZERO(IgnoreEmbeddedPointers, "%d"); TEST_ZERO(PointerBufferMark, "%p"); - TEST_ZERO(fBufferValid, "%d"); + TEST_ZERO(CorrDespIncrement, "%d"); TEST_ZERO(uFlags, "%d"); /* FIXME: UniquePtrCount */ TEST_ULONG_PTR_UNSET(MaxCount); @@ -1186,8 +1186,15 @@ static void test_client_init(void) TEST_ZERO(fHasReturn, "%d"); TEST_ZERO(fHasExtensions, "%d"); TEST_ZERO(fHasNewCorrDesc, "%d"); - TEST_ZERO(fUnused, "%d"); - ok(stubMsg.fUnused2 == 0xffffcccc, "stubMsg.fUnused2 should have been 0xcccc instead of 0x%x\n", stubMsg.fUnused2); + TEST_ZERO(fIsIn, "%d"); + TEST_ZERO(fIsOut, "%d"); + TEST_ZERO(fIsOicf, "%d"); + TEST_ZERO(fBufferValid, "%d"); + TEST_ZERO(fHasMemoryValidateCallback, "%d"); + TEST_ZERO(fInFree, "%d"); + TEST_ZERO(fNeedMCCP, "%d"); + TEST_ZERO(fUnused, "0x%x"); + ok(stubMsg.fUnused2 == 0xffffcccc, "stubMsg.fUnused2 should have been 0xffffcccc instead of 0x%x\n", stubMsg.fUnused2); ok(stubMsg.dwDestContext == MSHCTX_DIFFERENTMACHINE, "stubMsg.dwDestContext should have been MSHCTX_DIFFERENTMACHINE instead of %d\n", stubMsg.dwDestContext); TEST_ZERO(pvDestContext, "%p"); TEST_POINTER_UNSET(SavedContextHandles); @@ -1258,7 +1265,7 @@ todo_wine TEST_ZERO(pPointerQueueState, "%p"); TEST_ZERO(IgnoreEmbeddedPointers, "%d"); TEST_ZERO(PointerBufferMark, "%p"); - ok(stubMsg.fBufferValid == 0xcc, "fBufferValid should have been unset instead of 0x%x\n", stubMsg.fBufferValid); + ok(stubMsg.CorrDespIncrement == 0xcc, "CorrDespIncrement should have been unset instead of 0x%x\n", stubMsg.CorrDespIncrement); TEST_ZERO(uFlags, "%d"); /* FIXME: UniquePtrCount */ TEST_ULONG_PTR_UNSET(MaxCount); @@ -1280,8 +1287,15 @@ todo_wine TEST_ZERO(fHasReturn, "%d"); TEST_ZERO(fHasExtensions, "%d"); TEST_ZERO(fHasNewCorrDesc, "%d"); - TEST_ZERO(fUnused, "%d"); - ok(stubMsg.fUnused2 == 0xffffcccc, "stubMsg.fUnused2 should have been 0xcccc instead of 0x%x\n", stubMsg.fUnused2); + TEST_ZERO(fIsIn, "%d"); + TEST_ZERO(fIsOut, "%d"); + TEST_ZERO(fIsOicf, "%d"); + trace("fBufferValid = %d\n", stubMsg.fBufferValid); + TEST_ZERO(fHasMemoryValidateCallback, "%d"); + TEST_ZERO(fInFree, "%d"); + TEST_ZERO(fNeedMCCP, "%d"); + TEST_ZERO(fUnused, "0x%x"); + ok(stubMsg.fUnused2 == 0xffffcccc, "stubMsg.fUnused2 should have been 0xffffcccc instead of 0x%x\n", stubMsg.fUnused2); ok(stubMsg.dwDestContext == MSHCTX_DIFFERENTMACHINE, "stubMsg.dwDestContext should have been MSHCTX_DIFFERENTMACHINE instead of %d\n", stubMsg.dwDestContext); TEST_ZERO(pvDestContext, "%p"); TEST_POINTER_UNSET(SavedContextHandles); @@ -1799,6 +1813,7 @@ static void test_ndr_buffer(void) RPC_BINDING_HANDLE Handle; RPC_STATUS status; ULONG prev_buffer_length; + BOOL old_buffer_valid_location; StubDesc.RpcInterfaceInformation = (void *)&IFoo___RpcServerInterface; @@ -1834,7 +1849,11 @@ static void test_ndr_buffer(void) ok(!StubMsg.BufferEnd, "BufferEnd should have been NULL instead of %p\n", StubMsg.BufferEnd); todo_wine ok(StubMsg.BufferLength == 0, "BufferLength should have left as 0 instead of being set to %d\n", StubMsg.BufferLength); - ok(StubMsg.fBufferValid == TRUE, "fBufferValid should have been TRUE instead of 0x%x\n", StubMsg.fBufferValid); + old_buffer_valid_location = !StubMsg.fBufferValid; + if (old_buffer_valid_location) + ok(broken(StubMsg.CorrDespIncrement == TRUE), "fBufferValid should have been TRUE instead of 0x%x\n", StubMsg.CorrDespIncrement); + else + ok(StubMsg.fBufferValid, "fBufferValid should have been non-zero instead of 0x%x\n", StubMsg.fBufferValid); prev_buffer_length = RpcMessage.BufferLength; StubMsg.BufferLength = 1; @@ -1844,7 +1863,10 @@ todo_wine ok(RpcMessage.BufferLength == prev_buffer_length, "RpcMessage.BufferLength should have been left as %d instead of %d\n", prev_buffer_length, RpcMessage.BufferLength); ok(StubMsg.Buffer != NULL, "Buffer should not have been NULL\n"); ok(StubMsg.BufferLength == 1, "BufferLength should have left as 1 instead of being set to %d\n", StubMsg.BufferLength); - ok(StubMsg.fBufferValid == FALSE, "fBufferValid should have been FALSE instead of 0x%x\n", StubMsg.fBufferValid); + if (old_buffer_valid_location) + ok(broken(StubMsg.CorrDespIncrement == FALSE), "fBufferValid should have been FALSE instead of 0x%x\n", StubMsg.CorrDespIncrement); + else + ok(!StubMsg.fBufferValid, "fBufferValid should have been FALSE instead of %d\n", StubMsg.fBufferValid); /* attempt double-free */ NdrFreeBuffer(&StubMsg); diff --git a/dlls/rpcrt4/tests/rpc.c b/dlls/rpcrt4/tests/rpc.c index 035cde7bd89..490a15149ee 100644 --- a/dlls/rpcrt4/tests/rpc.c +++ b/dlls/rpcrt4/tests/rpc.c @@ -260,6 +260,10 @@ todo_wine { ok(status == RPC_S_OK, "RpcBindingFromStringBinding failed (%lu)\n", status); + status = RpcBindingSetAuthInfo(IFoo_IfHandle, NULL, RPC_C_AUTHN_LEVEL_NONE, + RPC_C_AUTHN_WINNT, NULL, RPC_C_AUTHZ_NAME); + ok(status == RPC_S_OK, "RpcBindingSetAuthInfo failed (%lu)\n", status); + status = RpcMgmtStopServerListening(NULL); ok(status == RPC_S_OK, "RpcMgmtStopServerListening failed (%lu)\n", status); @@ -672,6 +676,52 @@ static void test_I_RpcExceptionFilter(void) } } +static void test_endpoint_mapper(void) +{ + static unsigned char annotation[] = "Test annotation string."; + static unsigned char ncacn_ip_tcp[] = "ncacn_np"; + static unsigned char address[] = "."; + static unsigned char endpoint[] = "\\pipe\\wine_rpc_test"; + RPC_STATUS status; + RPC_BINDING_VECTOR *binding_vector; + handle_t handle; + unsigned char *binding; + + status = RpcServerUseProtseqEp(ncacn_ip_tcp, 20, endpoint, NULL); + ok(status == RPC_S_OK, "RpcServerUseProtseqEp failed (%lu)\n", status); + + status = RpcServerRegisterIf(IFoo_v0_0_s_ifspec, NULL, NULL); + ok(status == RPC_S_OK, "RpcServerRegisterIf failed (%lu)\n", status); + + status = RpcServerInqBindings(&binding_vector); + ok(status == RPC_S_OK, "RpcServerInqBindings failed with error %lu\n", status); + + status = RpcEpRegisterA(IFoo_v0_0_s_ifspec, binding_vector, NULL, annotation); + ok(status == RPC_S_OK, "RpcEpRegisterA failed with error %lu\n", status); + + status = RpcStringBindingCompose(NULL, ncacn_ip_tcp, address, + NULL, NULL, &binding); + ok(status == RPC_S_OK, "RpcStringBindingCompose failed (%lu)\n", status); + + status = RpcBindingFromStringBinding(binding, &handle); + ok(status == RPC_S_OK, "RpcBindingFromStringBinding failed (%lu)\n", status); + + status = RpcEpResolveBinding(handle, IFoo_v0_0_s_ifspec); + ok(status == RPC_S_OK, "RpcEpResolveBinding failed with error %lu\n", status); + + status = RpcBindingFree(&handle); + ok(status == RPC_S_OK, "RpcBindingFree failed with error %lu\n", status); + + status = RpcServerUnregisterIf(NULL, NULL, FALSE); + ok(status == RPC_S_OK, "RpcServerUnregisterIf failed (%lu)\n", status); + + status = RpcEpUnregister(IFoo_v0_0_s_ifspec, binding_vector, NULL); + ok(status == RPC_S_OK, "RpcEpUnregisterA failed with error %lu\n", status); + + status = RpcBindingVectorFree(&binding_vector); + ok(status == RPC_S_OK, "RpcBindingVectorFree failed with error %lu\n", status); +} + START_TEST( rpc ) { trace ( " ** Uuid Conversion and Comparison Tests **\n" ); @@ -683,4 +733,5 @@ START_TEST( rpc ) test_I_RpcMapWin32Status(); test_RpcStringBindingParseA(); test_I_RpcExceptionFilter(); + test_endpoint_mapper(); } diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c index 6c0527ff0ce..69b9ba40db3 100644 --- a/dlls/rpcrt4/tests/server.c +++ b/dlls/rpcrt4/tests/server.c @@ -654,6 +654,24 @@ s_get_numbers(int length, int size, pints_t n[]) } void +s_get_numbers_struct(numbers_struct_t **ns) +{ + int i; + *ns = midl_user_allocate(FIELD_OFFSET(numbers_struct_t, numbers[5])); + if (!*ns) return; + (*ns)->length = 5; + (*ns)->size = 5; + for (i = 0; i < (*ns)->length; i++) + { + (*ns)->numbers[i].pi = NULL; + (*ns)->numbers[i].ppi = NULL; + (*ns)->numbers[i].pppi = NULL; + } + (*ns)->numbers[0].pi = midl_user_allocate(sizeof(*(*ns)->numbers[i].pi)); + *(*ns)->numbers[0].pi = 5; +} + +void s_stop(void) { ok(RPC_S_OK == RpcMgmtStopServerListening(NULL), "RpcMgmtStopServerListening\n"); @@ -1096,6 +1114,7 @@ array_tests(void) doub_carr_t *dc; int *pi; pints_t api[5]; + numbers_struct_t *ns; ok(cstr_length(str1, sizeof str1) == strlen(str1), "RPC cstr_length\n"); @@ -1177,12 +1196,22 @@ array_tests(void) api[0].pi = pi; get_5numbers(1, api); ok(api[0].pi == pi, "RPC varying array [out] pointer changed from %p to %p\n", pi, api[0].pi); - ok(*api[0].pi == 0, "pi unmarshalled incorrectly %d\n", *pi); + ok(*api[0].pi == 0, "pi unmarshalled incorrectly %d\n", *api[0].pi); api[0].pi = pi; get_numbers(1, 1, api); ok(api[0].pi == pi, "RPC conformant varying array [out] pointer changed from %p to %p\n", pi, api[0].pi); - ok(*api[0].pi == 0, "pi unmarshalled incorrectly %d\n", *pi); + ok(*api[0].pi == 0, "pi unmarshalled incorrectly %d\n", *api[0].pi); + + ns = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(numbers_struct_t, numbers[5])); + ns->length = 5; + ns->size = 5; + ns->numbers[0].pi = pi; + get_numbers_struct(&ns); + ok(ns->numbers[0].pi == pi, "RPC conformant varying struct embedded pointer changed from %p to %p\n", pi, ns->numbers[0].pi); + ok(*ns->numbers[0].pi == 5, "pi unmarshalled incorrectly %d\n", *ns->numbers[0].pi); + + HeapFree(GetProcessHeap(), 0, ns); HeapFree(GetProcessHeap(), 0, pi); } diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl index 33e3a480a1c..378b205d80a 100644 --- a/dlls/rpcrt4/tests/server.idl +++ b/dlls/rpcrt4/tests/server.idl @@ -319,8 +319,17 @@ cpp_quote("#endif") type as a return value. */ s123_t *get_s123(void); + typedef struct + { + unsigned int length; + unsigned int size; + [size_is(size), length_is(length)] pints_t numbers[]; + } numbers_struct_t; + void get_5numbers([in] int count, [out, length_is(count)] pints_t pn[5]); void get_numbers([in] int length, [in] int size, [out, length_is(length), size_is(size)] pints_t pn[]); + void get_numbers_struct([out] numbers_struct_t **ns); + str_t get_filename(void); void context_handle_test(void); void stop(void); diff --git a/dlls/secur32/tests/schannel.c b/dlls/secur32/tests/schannel.c index c6d6052b279..b4eaf124193 100644 --- a/dlls/secur32/tests/schannel.c +++ b/dlls/secur32/tests/schannel.c @@ -216,7 +216,8 @@ static void testAcquireSecurityContext(void) st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &cred, NULL); ok(st == SEC_E_OK, "AcquireCredentialsHandleA failed: %08x\n", st); - pFreeCredentialsHandle(&cred); + if(st == SEC_E_OK) + pFreeCredentialsHandle(&cred); memset(&cred, 0, sizeof(cred)); st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &cred, &exp); diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 481eaa47a02..8fcff08dc9d 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -89,6 +89,39 @@ static void init_function_pointers(void) pSetupDiGetDeviceRegistryPropertyW = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyW"); } +static void change_reg_permissions(const WCHAR *regkey) +{ + HKEY hkey; + SID_IDENTIFIER_AUTHORITY ident = { SECURITY_WORLD_SID_AUTHORITY }; + SECURITY_DESCRIPTOR sd; + PSID EveryoneSid; + PACL pacl = NULL; + + RegOpenKeyExW(HKEY_LOCAL_MACHINE, regkey, 0, WRITE_DAC, &hkey); + + /* Initialize the 'Everyone' sid */ + AllocateAndInitializeSid(&ident, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid); + + pacl = HeapAlloc(GetProcessHeap(), 0, 256); + InitializeAcl(pacl, 256, ACL_REVISION); + + /* Add 'Full Control' for 'Everyone' */ + AddAccessAllowedAce(pacl, ACL_REVISION, KEY_ALL_ACCESS, EveryoneSid); + + InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); + + SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE); + + /* Set the new security on the registry key */ + RegSetKeySecurity(hkey, DACL_SECURITY_INFORMATION, &sd); + + RegCloseKey(hkey); + + HeapFree(GetProcessHeap(), 0, pacl); + if (EveryoneSid) + FreeSid(EveryoneSid); +} + static BOOL remove_device(void) { HDEVINFO set; @@ -336,20 +369,9 @@ static void testInstallClass(void) '{','6','a','5','5','b','5','a','4','-','3','f','6','5','-', '1','1','d','b','-','b','7','0','4','-', '0','0','1','1','9','5','5','c','2','b','d','b','}',0}; - static const CHAR classKey_win9x[] = - "System\\CurrentControlSet\\Services\\Class\\" - "{6a55b5a4-3f65-11db-b704-0011955c2bdb}"; - static const CHAR bogus_win9x[] = - "System\\CurrentControlSet\\Services\\Class\\Bogus"; char tmpfile[MAX_PATH]; BOOL ret; - HKEY hkey; - if (!pSetupDiInstallClassA) - { - skip("No SetupDiInstallClassA\n"); - return; - } tmpfile[0] = '.'; tmpfile[1] = '\\'; get_temp_filename(tmpfile + 2); @@ -372,21 +394,10 @@ static void testInstallClass(void) */ ret = pSetupDiInstallClassA(NULL, tmpfile, 0, NULL); ok(ret, "SetupDiInstallClassA failed: %08x\n", GetLastError()); - if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, classKey_win9x, &hkey)) - { - /* We are on win9x */ - RegCloseKey(hkey); - ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, classKey_win9x), - "Couldn't delete win9x classkey\n"); - ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, bogus_win9x), - "Couldn't delete win9x bogus services class\n"); - } - else - { - /* NT4 and above */ - ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey), - "Couldn't delete NT classkey\n"); - } + + ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, classKey), + "Couldn't delete classkey\n"); + DeleteFile(tmpfile); } @@ -401,30 +412,13 @@ static void testCreateDeviceInfo(void) 'E','n','u','m','\\','R','o','o','t','\\', 'L','E','G','A','C','Y','_','B','O','G','U','S',0}; - if (!pSetupDiCreateDeviceInfoList || !pSetupDiEnumDeviceInfo || - !pSetupDiDestroyDeviceInfoList || !pSetupDiCreateDeviceInfoA) - { - skip("No SetupDiCreateDeviceInfoA\n"); - return; - } SetLastError(0xdeadbeef); ret = pSetupDiCreateDeviceInfoA(NULL, NULL, NULL, NULL, NULL, 0, NULL); ok(!ret, "Expected failure\n"); ok(GetLastError() == ERROR_INVALID_DEVINST_NAME || - GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */ || - GetLastError() == ERROR_INVALID_HANDLE /* Win9x */, + GetLastError() == ERROR_INVALID_PARAMETER /* NT4 */, "Unexpected last error, got %08x\n", GetLastError()); - /* If we are running on win9x we should skip these tests. Win95 - * fails most tests anyway and win98 pops up the "Add New Hardware - * Wizard". - */ - if (GetLastError() == ERROR_INVALID_HANDLE) - { - skip("We are on win9x where the tests introduce issues\n"); - return; - } - SetLastError(0xdeadbeef); ret = pSetupDiCreateDeviceInfoA(NULL, "Root\\LEGACY_BOGUS\\0000", NULL, NULL, NULL, 0, NULL); @@ -439,19 +433,46 @@ static void testCreateDeviceInfo(void) DWORD i; static GUID deadbeef = {0xdeadbeef, 0xdead, 0xbeef, {0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef}}; + LONG res; + HKEY key; + static const WCHAR bogus0000[] = {'S','y','s','t','e','m','\\', + 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'E','n','u','m','\\','R','o','o','t','\\', + 'L','E','G','A','C','Y','_','B','O','G','U','S','\\','0','0','0','0',0}; + /* So we know we have a clean start */ + res = RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus0000, &key); + ok(res != ERROR_SUCCESS, "Expected key to not exist\n"); /* No GUID given */ SetLastError(0xdeadbeef); ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", NULL, NULL, NULL, 0, NULL); ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); + /* Even though NT4 fails it still adds some stuff to the registry that + * can't be deleted via normal setupapi functions. As the registry is written + * by a different user (SYSTEM) we have to do some magic to get rid of the key + */ + if (!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus0000, &key)) + { + trace("NT4 created a bogus key on failure, will be removed now\n"); + change_reg_permissions(bogus0000); + ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus0000), + "Could not delete LEGACY_BOGUS\\0000 key\n"); + } /* We can't add device information to the set with a different GUID */ SetLastError(0xdeadbeef); ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &deadbeef, NULL, NULL, 0, NULL); ok(!ret && GetLastError() == ERROR_CLASS_MISMATCH, "Expected ERROR_CLASS_MISMATCH, got %08x\n", GetLastError()); + if (!RegOpenKeyW(HKEY_LOCAL_MACHINE, bogus0000, &key)) + { + trace("NT4 created a bogus key on failure, will be removed now\n"); + change_reg_permissions(bogus0000); + ok(!RegDeleteKeyW(HKEY_LOCAL_MACHINE, bogus0000), + "Could not delete LEGACY_BOGUS\\0000 key\n"); + } /* Finally, with all three required parameters, this succeeds: */ ret = pSetupDiCreateDeviceInfoA(set, "Root\\LEGACY_BOGUS\\0000", &guid, NULL, NULL, 0, NULL); @@ -530,12 +551,6 @@ static void testGetDeviceInstanceId(void) HDEVINFO set; SP_DEVINFO_DATA devInfo = { 0 }; - if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList || - !pSetupDiCreateDeviceInfoA || !pSetupDiGetDeviceInstanceIdA) - { - skip("No SetupDiGetDeviceInstanceIdA\n"); - return; - } SetLastError(0xdeadbeef); ret = pSetupDiGetDeviceInstanceIdA(NULL, NULL, NULL, 0, NULL); ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, @@ -587,7 +602,8 @@ static void testGetDeviceInstanceId(void) ret = pSetupDiGetDeviceInstanceIdA(set, &devInfo, instanceID, sizeof(instanceID), NULL); ok(ret, "SetupDiGetDeviceInstanceIdA failed: %08x\n", GetLastError()); - ok(!lstrcmpA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"), + /* NT4 returns 'Root' and W2K and above 'ROOT' */ + ok(!lstrcmpiA(instanceID, "ROOT\\LEGACY_BOGUS\\0001"), "Unexpected instance ID %s\n", instanceID); pSetupDiDestroyDeviceInfoList(set); } @@ -598,12 +614,6 @@ static void testRegisterDeviceInfo(void) BOOL ret; HDEVINFO set; - if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList || - !pSetupDiRegisterDeviceInfo) - { - skip("No SetupDiRegisterDeviceInfo\n"); - return; - } SetLastError(0xdeadbeef); ret = pSetupDiRegisterDeviceInfo(NULL, NULL, 0, NULL, NULL, NULL); ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, @@ -639,8 +649,7 @@ static void testRegisterDeviceInfo(void) ok(ret, "SetupDiCreateDeviceInfoA failed: %d\n", GetLastError()); } /* FIXME: On Win2K+ systems, this is now persisted to registry in - * HKLM\System\CCS\Enum\USB\Bogus\0000. I don't check because the - * Win9x location is different. + * HKLM\System\CCS\Enum\USB\Bogus\0000. * FIXME: the key also becomes undeletable. How to get rid of it? */ pSetupDiDestroyDeviceInfoList(set); @@ -663,11 +672,9 @@ static void testCreateDeviceInterface(void) '1','1','d','b','-','b','7','0','4','-', '0','0','1','1','9','5','5','c','2','b','d','b','}',0}; - if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList || - !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA || - !pSetupDiEnumDeviceInterfaces) + if (!pSetupDiCreateDeviceInterfaceA || !pSetupDiEnumDeviceInterfaces) { - skip("No SetupDiCreateDeviceInterfaceA\n"); + skip("SetupDiCreateDeviceInterfaceA and/or SetupDiEnumDeviceInterfaces are not available\n"); return; } SetLastError(0xdeadbeef); @@ -762,11 +769,9 @@ static void testGetDeviceInterfaceDetail(void) '1','1','d','b','-','b','7','0','4','-', '0','0','1','1','9','5','5','c','2','b','d','b','}',0}; - if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList || - !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA || - !pSetupDiGetDeviceInterfaceDetailA) + if (!pSetupDiCreateDeviceInterfaceA || !pSetupDiGetDeviceInterfaceDetailA) { - skip("No SetupDiGetDeviceInterfaceDetailA\n"); + skip("SetupDiCreateDeviceInterfaceA and/or SetupDiGetDeviceInterfaceDetailA are not available\n"); return; } SetLastError(0xdeadbeef); @@ -839,9 +844,7 @@ static void testGetDeviceInterfaceDetail(void) size, &size, NULL); ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); - /* Windows 2000 and up check for the exact size. Win9x returns ERROR_INVALID_PARAMETER - * on every call (so doesn't get here) and NT4 doesn't have this function. - */ + /* Windows 2000 and up check for the exact size */ detail->cbSize = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]); ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail, size, &size, NULL); @@ -851,18 +854,13 @@ static void testGetDeviceInterfaceDetail(void) !lstrcmpiA(path_w2k, detail->DevicePath), "Unexpected path %s\n", detail->DevicePath); /* Check SetupDiGetDeviceInterfaceDetailW */ - if (pSetupDiGetDeviceInterfaceDetailW) - { - ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, NULL); - ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, - "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError()); - ok(expectedsize == size || - (expectedsize + sizeof(WCHAR)) == size /* W2K adds a backslash */, - "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize, got %d\n", - size); - } - else - skip("SetupDiGetDeviceInterfaceDetailW is not available\n"); + ret = pSetupDiGetDeviceInterfaceDetailW(set, &interfaceData, NULL, 0, &size, NULL); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Expected ERROR_INSUFFICIENT_BUFFER, got error code: %d\n", GetLastError()); + ok(expectedsize == size || + (expectedsize + sizeof(WCHAR)) == size /* W2K adds a backslash */, + "SetupDiGetDeviceInterfaceDetailW returned wrong reqsize, got %d\n", + size); HeapFree(GetProcessHeap(), 0, buf); } @@ -903,23 +901,8 @@ static void testDevRegKey(void) HDEVINFO set; HKEY key = NULL; - if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList || - !pSetupDiCreateDeviceInfoA || !pSetupDiOpenDevRegKey || - !pSetupDiRegisterDeviceInfo || !pSetupDiCreateDevRegKeyW || - !pSetupDiCallClassInstaller) - { - skip("No SetupDiOpenDevRegKey\n"); - return; - } - - /* Check if we are on win9x */ SetLastError(0xdeadbeef); key = pSetupDiCreateDevRegKeyW(NULL, NULL, 0, 0, 0, NULL, NULL); - if (key == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) - { - skip("We are on win9x where the tests introduce issues\n"); - return; - } ok(key == INVALID_HANDLE_VALUE, "Expected INVALID_HANDLE_VALUE, got %p\n", key); ok(GetLastError() == ERROR_INVALID_HANDLE, @@ -1070,6 +1053,13 @@ static void testRegisterAndGetDetail(void) '1','1','d','b','-','b','7','0','4','-', '0','0','1','1','9','5','5','c','2','b','d','b','}',0}; + if (!pSetupDiCreateDeviceInterfaceA || !pSetupDiEnumDeviceInterfaces || + !pSetupDiGetDeviceInterfaceDetailA) + { + skip("Needed functions are not available\n"); + return; + } + SetLastError(0xdeadbeef); set = pSetupDiGetClassDevsA(&guid, NULL, 0, DIGCF_ALLCLASSES); ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsA failed: %08x\n", @@ -1272,11 +1262,6 @@ static void testDeviceRegistryPropertyW() SetLastError(0xdeadbeef); set = pSetupDiGetClassDevsW(&guid, NULL, 0, DIGCF_DEVICEINTERFACE); - if (set == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) - { - skip("W-functions are not implemented\n"); - return; - } ok(set != INVALID_HANDLE_VALUE, "SetupDiGetClassDevsW failed: %08x\n", GetLastError()); SetLastError(0xdeadbeef); @@ -1365,17 +1350,32 @@ static void testDeviceRegistryPropertyW() START_TEST(devinst) { - init_function_pointers(); + HDEVINFO set; + + init_function_pointers(); - if (pSetupDiCreateDeviceInfoListExW && pSetupDiDestroyDeviceInfoList) + /* Win9x/WinMe does things totally different so we skip all the tests + * + * We don't want to exclude NT4 so hence this check. + */ + SetLastError(0xdeadbeef); + set = pSetupDiGetClassDevsW(NULL, NULL, 0, 0); + if (set == INVALID_HANDLE_VALUE && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + skip("Win9x/WinMe has totally different behavior\n"); + return; + } + + if (pSetupDiCreateDeviceInfoListExW) test_SetupDiCreateDeviceInfoListEx(); else - skip("SetupDiCreateDeviceInfoListExW and/or SetupDiDestroyDeviceInfoList not available\n"); + skip("SetupDiCreateDeviceInfoListExW is not available\n"); if (pSetupDiOpenClassRegKeyExA) test_SetupDiOpenClassRegKeyExA(); else skip("SetupDiOpenClassRegKeyExA is not available\n"); + testInstallClass(); testCreateDeviceInfo(); testGetDeviceInstanceId(); diff --git a/dlls/setupapi/tests/install.c b/dlls/setupapi/tests/install.c index 0044f019e4b..ff3be6d5335 100644 --- a/dlls/setupapi/tests/install.c +++ b/dlls/setupapi/tests/install.c @@ -137,6 +137,44 @@ static void test_cmdline(void) ok(DeleteFile(infwithspaces), "Expected source inf to exist, last error was %d\n", GetLastError()); } +static const char *cmdline_inf_reg = "[Version]\n" + "Signature=\"$Chicago$\"\n" + "[DefaultInstall]\n" + "DelReg=Del.Settings\n" + "[Del.Settings]\n" + "HKCU,Software\\Wine\\setupapitest\n"; + +static void test_registry(void) +{ + HKEY key; + LONG res; + char path[MAX_PATH]; + + /* First create a registry structure we would like to be deleted */ + ok(!RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest", &key), + "Expected RegCreateKeyA to succeed\n"); + + /* Doublecheck if the registry key is present */ + ok(!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest", &key), + "Expected registry key to exist\n"); + + create_inf_file(inffile, cmdline_inf_reg); + sprintf(path, "%s\\%s", CURR_DIR, inffile); + run_cmdline("DefaultInstall", 128, path); + + /* Check if the registry key is recursively deleted */ + res = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest", &key); + todo_wine + ok(res == ERROR_FILE_NOT_FOUND, "Didn't expect the registry key to exist\n"); + /* Just in case */ + if (res == ERROR_SUCCESS) + { + RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest"); + RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest"); + } + ok(DeleteFile(inffile), "Expected source inf to exist, last error was %d\n", GetLastError()); +} + static void test_install_svc_from(void) { char inf[2048]; @@ -386,6 +424,7 @@ START_TEST(install) assert(hhook != 0); test_cmdline(); + test_registry(); test_install_svc_from(); test_driver_install(); diff --git a/dlls/shdocvw/webbrowser.c b/dlls/shdocvw/webbrowser.c index 50c3b347dcf..3699239821d 100644 --- a/dlls/shdocvw/webbrowser.c +++ b/dlls/shdocvw/webbrowser.c @@ -165,16 +165,29 @@ static ULONG WINAPI WebBrowser_Release(IWebBrowser2 *iface) static HRESULT WINAPI WebBrowser_GetTypeInfoCount(IWebBrowser2 *iface, UINT *pctinfo) { WebBrowser *This = WEBBROWSER_THIS(iface); - FIXME("(%p)->(%p)\n", This, pctinfo); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, pctinfo); + + *pctinfo = 1; + return S_OK; } static HRESULT WINAPI WebBrowser_GetTypeInfo(IWebBrowser2 *iface, UINT iTInfo, LCID lcid, LPTYPEINFO *ppTInfo) { WebBrowser *This = WEBBROWSER_THIS(iface); - FIXME("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo); - return E_NOTIMPL; + ITypeInfo *typeinfo; + HRESULT hres; + + TRACE("(%p)->(%d %d %p)\n", This, iTInfo, lcid, ppTInfo); + + hres = get_typeinfo(&typeinfo); + if(FAILED(hres)) + return hres; + + ITypeInfo_AddRef(typeinfo); + *ppTInfo = typeinfo; + return S_OK; } static HRESULT WINAPI WebBrowser_GetIDsOfNames(IWebBrowser2 *iface, REFIID riid, @@ -182,9 +195,17 @@ static HRESULT WINAPI WebBrowser_GetIDsOfNames(IWebBrowser2 *iface, REFIID riid, LCID lcid, DISPID *rgDispId) { WebBrowser *This = WEBBROWSER_THIS(iface); - FIXME("(%p)->(%s %p %d %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, - lcid, rgDispId); - return E_NOTIMPL; + ITypeInfo *typeinfo; + HRESULT hres; + + TRACE("(%p)->(%s %p %d %d %p)\n", This, debugstr_guid(riid), rgszNames, cNames, + lcid, rgDispId); + + hres = get_typeinfo(&typeinfo); + if(FAILED(hres)) + return hres; + + return ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); } static HRESULT WINAPI WebBrowser_Invoke(IWebBrowser2 *iface, DISPID dispIdMember, diff --git a/dlls/shell32/control.c b/dlls/shell32/control.c index 1f17016c70e..7afe8e9c7db 100644 --- a/dlls/shell32/control.c +++ b/dlls/shell32/control.c @@ -358,7 +358,8 @@ static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd) LPWSTR end; WCHAR ch; LPWSTR ptr; - unsigned sp = 0; + signed sp = -1; + LPWSTR extraPmtsBuf = NULL; LPWSTR extraPmts = NULL; int quoted = 0; @@ -368,46 +369,92 @@ static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd) end = lstrcpyW(buffer, wszCmd); for (;;) { - ch = *end; + ch = *end; if (ch == '"') quoted = !quoted; - if (!quoted && (ch == ' ' || ch == ',' || ch == '\0')) { - *end = '\0'; - if (beg) { - if (*beg == '@') { - sp = atoiW(beg + 1); - } else if (*beg == '\0') { - sp = 0; - } else { - extraPmts = beg; - } - } - if (ch == '\0') break; - beg = end + 1; - if (ch == ' ') while (end[1] == ' ') end++; - } - end++; + if (!quoted && (ch == ' ' || ch == ',' || ch == '\0')) { + *end = '\0'; + if (beg) { + if (*beg == '@') { + sp = atoiW(beg + 1); + } else if (*beg == '\0') { + sp = -1; + } else { + extraPmtsBuf = beg; + } + } + if (ch == '\0') break; + beg = end + 1; + if (ch == ' ') while (end[1] == ' ') end++; + } + end++; } while ((ptr = StrChrW(buffer, '"'))) memmove(ptr, ptr+1, lstrlenW(ptr)*sizeof(WCHAR)); + /* now check for any quotes in extraPmtsBuf and remove */ + if (extraPmtsBuf != NULL) + { + beg = end = extraPmtsBuf; + quoted = 0; + + for (;;) { + ch = *end; + if (ch == '"') quoted = !quoted; + if (!quoted && (ch == ' ' || ch == ',' || ch == '\0')) { + *end = '\0'; + if (beg) { + if (*beg != '\0') { + extraPmts = beg; + } + } + if (ch == '\0') break; + beg = end + 1; + if (ch == ' ') while (end[1] == ' ') end++; + } + end++; + } + + while ((ptr = StrChrW(extraPmts, '"'))) + memmove(ptr, ptr+1, lstrlenW(ptr)*sizeof(WCHAR)); + + if (extraPmts == NULL) + extraPmts = extraPmtsBuf; + } + TRACE("cmd %s, extra %s, sp %d\n", debugstr_w(buffer), debugstr_w(extraPmts), sp); Control_LoadApplet(hWnd, buffer, panel); if (panel->first) { - CPlApplet* applet = panel->first; + CPlApplet* applet = panel->first; - assert(applet && applet->next == NULL); - if (sp >= applet->count) { - WARN("Out of bounds (%u >= %u), setting to 0\n", sp, applet->count); - sp = 0; - } - if (applet->info[sp].dwSize) { - if (!applet->proc(applet->hWnd, CPL_STARTWPARMSA, sp, (LPARAM)extraPmts)) - applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].lData); - } - Control_UnloadApplet(applet); + assert(applet && applet->next == NULL); + + /* we've been given a textual parameter (or none at all) */ + if (sp == -1) { + while ((++sp) != applet->count) { + if (applet->info[sp].dwSize) { + TRACE("sp %d, name %s\n", sp, debugstr_w(applet->info[sp].szName)); + + if (StrCmpIW(extraPmts, applet->info[sp].szName) == 0) + break; + } + } + } + + if (sp >= applet->count) { + WARN("Out of bounds (%u >= %u), setting to 0\n", sp, applet->count); + sp = 0; + } + + if (applet->info[sp].dwSize) { + if (!applet->proc(applet->hWnd, CPL_STARTWPARMSA, sp, (LPARAM)extraPmts)) + applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].lData); + } + + Control_UnloadApplet(applet); } + HeapFree(GetProcessHeap(), 0, buffer); } diff --git a/dlls/shell32/cpanelfolder.c b/dlls/shell32/cpanelfolder.c index 85c8974561b..e3f9ffbcd89 100644 --- a/dlls/shell32/cpanelfolder.c +++ b/dlls/shell32/cpanelfolder.c @@ -111,7 +111,7 @@ static inline ICPanelImpl *impl_from_IShellExecuteHookA( IShellExecuteHookA *ifa static const shvheader ControlPanelSFHeader[] = { {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},/*FIXME*/ - {IDS_SHV_COLUMN9, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 200},/*FIXME*/ + {IDS_SHV_COLUMN9, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 80},/*FIXME*/ }; #define CONROLPANELSHELLVIEWCOLUMNS 2 @@ -764,6 +764,7 @@ static HRESULT WINAPI ISF_ControlPanel_fnGetDetailsEx(IShellFolder2 * iface, LPC static HRESULT WINAPI ISF_ControlPanel_fnGetDetailsOf(IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd) { ICPanelImpl *This = (ICPanelImpl *)iface; + PIDLCPanelStruct* pcpanel; HRESULT hr; TRACE("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd); @@ -785,7 +786,13 @@ static HRESULT WINAPI ISF_ControlPanel_fnGetDetailsOf(IShellFolder2 * iface, LPC hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str); break; case 1: /* comment */ - _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH); + pcpanel = _ILGetCPanelPointer(pidl); + + if (pcpanel) + lstrcpyA(psd->str.u.cStr, pcpanel->szName+pcpanel->offsComment); + else + _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH); + break; } hr = S_OK; diff --git a/dlls/shell32/iconcache.c b/dlls/shell32/iconcache.c index 7345010d256..dc4a3ef043f 100644 --- a/dlls/shell32/iconcache.c +++ b/dlls/shell32/iconcache.c @@ -840,3 +840,28 @@ HRESULT WINAPI SHDefExtractIconA(LPCSTR pszIconFile, int iIndex, UINT uFlags, HeapFree(GetProcessHeap(), 0, lpwstrFile); return ret; } + + +/**************************************************************************** + * SHGetIconOverlayIndexA [SHELL32.@] + * + * Returns the index of the overlay icon in the system image list. + */ +INT WINAPI SHGetIconOverlayIndexA(LPCSTR pszIconPath, INT iIconIndex) +{ + FIXME("%s, %d\n", debugstr_a(pszIconPath), iIconIndex); + + return -1; +} + +/**************************************************************************** + * SHGetIconOverlayIndexW [SHELL32.@] + * + * Returns the index of the overlay icon in the system image list. + */ +INT WINAPI SHGetIconOverlayIndexW(LPCWSTR pszIconPath, INT iIconIndex) +{ + FIXME("%s, %d\n", debugstr_w(pszIconPath), iIconIndex); + + return -1; +} diff --git a/dlls/shell32/regsvr.c b/dlls/shell32/regsvr.c index 199a9dc12de..028ca0ac97a 100644 --- a/dlls/shell32/regsvr.c +++ b/dlls/shell32/regsvr.c @@ -80,8 +80,10 @@ struct regsvr_coclass /* flags for regsvr_coclass.flags */ #define SHELLEX_MAYCHANGEDEFAULTMENU 0x00000001 #define SHELLFOLDER_WANTSFORPARSING 0x00000002 -#define SHELLFOLDER_ATTRIBUTES 0x00000004 -#define SHELLFOLDER_CALLFORATTRIBUTES 0x00000008 +#define SHELLFOLDER_WANTSFORDISPLAY 0x00000004 +#define SHELLFOLDER_ATTRIBUTES 0x00000008 +#define SHELLFOLDER_CALLFORATTRIBUTES 0x00000010 +#define SHELLFOLDER_HIDEASDELETE 0x00000020 static HRESULT register_coclasses(struct regsvr_coclass const *list); static HRESULT unregister_coclasses(struct regsvr_coclass const *list); @@ -133,9 +135,11 @@ static WCHAR const defaulticon_keyname[] = { 'D','e','f','a','u','l','t','I','c','o','n',0}; static char const tmodel_valuename[] = "ThreadingModel"; static char const wfparsing_valuename[] = "WantsFORPARSING"; +static char const wfdisplay_valuename[] = "WantsFORDISPLAY"; static char const attributes_valuename[] = "Attributes"; static char const cfattributes_valuename[] = "CallForAttributes"; static char const localized_valuename[] = "LocalizedString"; +static char const hideasdelete_valuename[] = "HideAsDeletePerUser"; /*********************************************************************** * static helper functions @@ -333,7 +337,7 @@ static HRESULT register_coclasses(struct regsvr_coclass const *list) } if (list->flags & - (SHELLFOLDER_WANTSFORPARSING|SHELLFOLDER_ATTRIBUTES|SHELLFOLDER_CALLFORATTRIBUTES)) + (SHELLFOLDER_WANTSFORPARSING|SHELLFOLDER_WANTSFORDISPLAY|SHELLFOLDER_ATTRIBUTES|SHELLFOLDER_CALLFORATTRIBUTES|SHELLFOLDER_HIDEASDELETE)) { HKEY shellfolder_key; @@ -343,6 +347,10 @@ static HRESULT register_coclasses(struct regsvr_coclass const *list) if (res != ERROR_SUCCESS) goto error_close_clsid_key; if (list->flags & SHELLFOLDER_WANTSFORPARSING) res = RegSetValueExA(shellfolder_key, wfparsing_valuename, 0, REG_SZ, (const BYTE *)"", 1); + if (list->flags & SHELLFOLDER_WANTSFORDISPLAY) + res = RegSetValueExA(shellfolder_key, wfdisplay_valuename, 0, REG_SZ, (const BYTE *)"", 1); + if (list->flags & SHELLFOLDER_HIDEASDELETE) + res = RegSetValueExA(shellfolder_key, hideasdelete_valuename, 0, REG_SZ, (const BYTE *)"", 1); if (list->flags & SHELLFOLDER_ATTRIBUTES) res = RegSetValueExA(shellfolder_key, attributes_valuename, 0, REG_DWORD, (const BYTE *)&list->dwAttributes, sizeof(DWORD)); @@ -649,6 +657,15 @@ static struct regsvr_coclass const coclass_list[] = { "shell32.dll", "Apartment" }, + { &CLSID_ControlPanel, + "Control Panel", + IDS_CONTROLPANEL, + NULL, + "shell32.dll", + "Apartment", + SHELLFOLDER_WANTSFORDISPLAY|SHELLFOLDER_ATTRIBUTES|SHELLFOLDER_HIDEASDELETE, + SFGAO_FOLDER|SFGAO_HASSUBFOLDER, + }, { NULL } /* list terminator */ }; @@ -667,6 +684,8 @@ static const WCHAR wszDesktop[] = { 'D','e','s','k','t','o','p',0 }; static const WCHAR wszSlash[] = { '/', 0 }; static const WCHAR wszMyDocuments[] = { 'M','y',' ','D','o','c','u','m','e','n','t','s', 0 }; static const WCHAR wszRecycleBin[] = { 'T','r','a','s','h', 0 }; +static const WCHAR wszMyComputer[] = { 'M','y','C','o','m','p','u','t','e','r', 0 }; +static const WCHAR wszControlPanel[] = { 'C','o','n','t','r','o','l',' ','P','a','n','e','l', 0 }; static struct regsvr_namespace const namespace_extensions_list[] = { { @@ -684,6 +703,11 @@ static struct regsvr_namespace const namespace_extensions_list[] = { wszDesktop, wszRecycleBin }, + { + &CLSID_ControlPanel, + wszMyComputer, + wszControlPanel + }, { NULL } }; diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec index e054db3d752..8bbabb995f5 100644 --- a/dlls/shell32/shell32.spec +++ b/dlls/shell32/shell32.spec @@ -348,8 +348,8 @@ @ stdcall SHGetFolderPathAndSubDirW(long long long long wstr ptr) @ stdcall SHGetFolderPathW(long long long long ptr) @ stub SHGetFreeDiskSpace -@ stub SHGetIconOverlayIndexA -@ stub SHGetIconOverlayIndexW +@ stdcall SHGetIconOverlayIndexA(str long) +@ stdcall SHGetIconOverlayIndexW(wstr long) @ stdcall SHGetInstanceExplorer(long) @ stdcall SHGetMalloc(ptr) @ stdcall SHGetNewLinkInfo(str str ptr long long) SHGetNewLinkInfoA diff --git a/dlls/shell32/shell32_Bg.rc b/dlls/shell32/shell32_Bg.rc index 99e7475598d..c969f02a694 100644 --- a/dlls/shell32/shell32_Bg.rc +++ b/dlls/shell32/shell32_Bg.rc @@ -154,6 +154,7 @@ STRINGTABLE /* special folders */ IDS_DESKTOP "Ðàáîòåí ïëîò" IDS_MYCOMPUTER "Ìîÿò êîìïþòúð" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "&Ãîëåìè èêîíè" diff --git a/dlls/shell32/shell32_Cs.rc b/dlls/shell32/shell32_Cs.rc index 8ae98523b92..af8cfeeb281 100644 --- a/dlls/shell32/shell32_Cs.rc +++ b/dlls/shell32/shell32_Cs.rc @@ -145,6 +145,7 @@ STRINGTABLE { IDS_DESKTOP "Plocha" IDS_MYCOMPUTER "Tento poèítaè" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "&Vedle sebe" diff --git a/dlls/shell32/shell32_Da.rc b/dlls/shell32/shell32_Da.rc index 63b99489aca..59f8c6260cf 100644 --- a/dlls/shell32/shell32_Da.rc +++ b/dlls/shell32/shell32_Da.rc @@ -187,6 +187,7 @@ STRINGTABLE IDS_DESKTOP "Skrivebord" IDS_MYCOMPUTER "Min Computer" IDS_RECYCLEBIN_FOLDER_NAME "Skraldespand" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "Store Ikoner" diff --git a/dlls/shell32/shell32_De.rc b/dlls/shell32/shell32_De.rc index 194ef09494f..e6dc749edd7 100644 --- a/dlls/shell32/shell32_De.rc +++ b/dlls/shell32/shell32_De.rc @@ -187,6 +187,7 @@ STRINGTABLE IDS_DESKTOP "Desktop" IDS_MYCOMPUTER "Arbeitsplatz" IDS_RECYCLEBIN_FOLDER_NAME "Papierkorb" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "&Große Symbole" diff --git a/dlls/shell32/shell32_En.rc b/dlls/shell32/shell32_En.rc index e2f476a7987..112d0331418 100644 --- a/dlls/shell32/shell32_En.rc +++ b/dlls/shell32/shell32_En.rc @@ -186,6 +186,7 @@ STRINGTABLE IDS_DESKTOP "Desktop" IDS_MYCOMPUTER "My Computer" IDS_RECYCLEBIN_FOLDER_NAME "Trash" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "Lar&ge Icons" diff --git a/dlls/shell32/shell32_Eo.rc b/dlls/shell32/shell32_Eo.rc index 775961d5c47..e5f16b0a52e 100644 --- a/dlls/shell32/shell32_Eo.rc +++ b/dlls/shell32/shell32_Eo.rc @@ -148,6 +148,7 @@ STRINGTABLE /* special folders */ IDS_DESKTOP "Desktop" IDS_MYCOMPUTER "Mea Komputero" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "&Grandaj Ikonoj" diff --git a/dlls/shell32/shell32_Es.rc b/dlls/shell32/shell32_Es.rc index 9314ba8a94d..15abaf1ead2 100644 --- a/dlls/shell32/shell32_Es.rc +++ b/dlls/shell32/shell32_Es.rc @@ -187,6 +187,7 @@ STRINGTABLE IDS_DESKTOP "Escritorio" IDS_MYCOMPUTER "Mi PC" IDS_RECYCLEBIN_FOLDER_NAME "Papelera de reciclaje" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "Iconos &grandes" diff --git a/dlls/shell32/shell32_Fi.rc b/dlls/shell32/shell32_Fi.rc index 9ab1a778633..acd143f73e2 100644 --- a/dlls/shell32/shell32_Fi.rc +++ b/dlls/shell32/shell32_Fi.rc @@ -154,6 +154,7 @@ STRINGTABLE /* special folders */ IDS_DESKTOP "Työpöytä" IDS_MYCOMPUTER "Oma tietokone" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "&Suuret kuvakkeet" diff --git a/dlls/shell32/shell32_Fr.rc b/dlls/shell32/shell32_Fr.rc index b68c74d49e3..9378b9411a2 100644 --- a/dlls/shell32/shell32_Fr.rc +++ b/dlls/shell32/shell32_Fr.rc @@ -192,6 +192,7 @@ STRINGTABLE IDS_DESKTOP "Bureau" IDS_MYCOMPUTER "Poste de travail" IDS_RECYCLEBIN_FOLDER_NAME "Corbeille" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "&Grandes icônes" diff --git a/dlls/shell32/shell32_It.rc b/dlls/shell32/shell32_It.rc index bbabe0c2aeb..1afdc328dd4 100644 --- a/dlls/shell32/shell32_It.rc +++ b/dlls/shell32/shell32_It.rc @@ -156,6 +156,7 @@ STRINGTABLE /* special folder */ IDS_DESKTOP "Desktop" IDS_MYCOMPUTER "Risorse del Computer" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "Icone &Grandi" diff --git a/dlls/shell32/shell32_Ja.rc b/dlls/shell32/shell32_Ja.rc index 0584a94dd6c..b858dc5915f 100644 --- a/dlls/shell32/shell32_Ja.rc +++ b/dlls/shell32/shell32_Ja.rc @@ -104,6 +104,7 @@ STRINGTABLE /* special folders */ IDS_DESKTOP "ÃÞ½¸Ä¯Ìß" IDS_MYCOMPUTER "ϲºÝËß­°À" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "‘å‚«‚¢ƒAƒCƒRƒ“(&G)" diff --git a/dlls/shell32/shell32_Ko.rc b/dlls/shell32/shell32_Ko.rc index 1f1b0e8d910..0379926614e 100644 --- a/dlls/shell32/shell32_Ko.rc +++ b/dlls/shell32/shell32_Ko.rc @@ -188,6 +188,7 @@ IDS_SHV_COLUMN_DELDATE " IDS_DESKTOP "µ¥½ºÅ©Å¾" IDS_MYCOMPUTER "³» ÄÄÇ»ÅÍ" IDS_RECYCLEBIN_FOLDER_NAME "ÈÞÁöÅë" +IDS_CONTROLPANEL "Á¦¾îÆÇ" /* context menus */ IDS_VIEW_LARGE "Å« ¾ÆÀÌÄÜ(&G)" diff --git a/dlls/shell32/shell32_Nl.rc b/dlls/shell32/shell32_Nl.rc index d22a07a3b0d..d50e0119674 100644 --- a/dlls/shell32/shell32_Nl.rc +++ b/dlls/shell32/shell32_Nl.rc @@ -188,6 +188,7 @@ STRINGTABLE IDS_DESKTOP "Bureaublad" IDS_MYCOMPUTER "Mijn Computer" IDS_RECYCLEBIN_FOLDER_NAME "Vuilnisbak" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "Grote Icons" diff --git a/dlls/shell32/shell32_No.rc b/dlls/shell32/shell32_No.rc index d85dce9c4c8..b6ad9672567 100644 --- a/dlls/shell32/shell32_No.rc +++ b/dlls/shell32/shell32_No.rc @@ -186,6 +186,7 @@ STRINGTABLE IDS_DESKTOP "Skrivebord" IDS_MYCOMPUTER "Min datamaskin" IDS_RECYCLEBIN_FOLDER_NAME "Papirkurv" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "&Store ikoner" diff --git a/dlls/shell32/shell32_Pl.rc b/dlls/shell32/shell32_Pl.rc index 4d29d6fc67c..6b9afdd3f1d 100644 --- a/dlls/shell32/shell32_Pl.rc +++ b/dlls/shell32/shell32_Pl.rc @@ -187,6 +187,7 @@ STRINGTABLE IDS_DESKTOP "Pulpit" IDS_MYCOMPUTER "Mój komputer" IDS_RECYCLEBIN_FOLDER_NAME "Kosz" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "&Du¿e Ikony" diff --git a/dlls/shell32/shell32_Pt.rc b/dlls/shell32/shell32_Pt.rc index 5ba9006d1b8..2934b414657 100644 --- a/dlls/shell32/shell32_Pt.rc +++ b/dlls/shell32/shell32_Pt.rc @@ -248,6 +248,7 @@ STRINGTABLE /* special folders */ IDS_DESKTOP "Área de trabalho" IDS_MYCOMPUTER "Meu computador" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "Ícones &grandes" diff --git a/dlls/shell32/shell32_Ro.rc b/dlls/shell32/shell32_Ro.rc index 273ce7fb9f3..36789ca75e0 100644 --- a/dlls/shell32/shell32_Ro.rc +++ b/dlls/shell32/shell32_Ro.rc @@ -189,6 +189,7 @@ STRINGTABLE IDS_DESKTOP "Birou" IDS_MYCOMPUTER "Computerul meu" IDS_RECYCLEBIN_FOLDER_NAME "Gunoi" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "Pictograme &mari" diff --git a/dlls/shell32/shell32_Ru.rc b/dlls/shell32/shell32_Ru.rc index 48a403e0cc7..808d6683655 100644 --- a/dlls/shell32/shell32_Ru.rc +++ b/dlls/shell32/shell32_Ru.rc @@ -187,6 +187,7 @@ STRINGTABLE IDS_DESKTOP "Ðàáî÷èé ñòîë" IDS_MYCOMPUTER "Ìîé êîìïüþòåð" IDS_RECYCLEBIN_FOLDER_NAME "Êîðçèíà" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "&Áîëüøèå çíà÷êè" diff --git a/dlls/shell32/shell32_Si.rc b/dlls/shell32/shell32_Si.rc index af7e5f2ab2b..ccf94200ae3 100644 --- a/dlls/shell32/shell32_Si.rc +++ b/dlls/shell32/shell32_Si.rc @@ -188,6 +188,7 @@ STRINGTABLE IDS_DESKTOP "Namizje" IDS_MYCOMPUTER "Moj računalnik" IDS_RECYCLEBIN_FOLDER_NAME "Smeti" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "Ve&like ikone" diff --git a/dlls/shell32/shell32_Tr.rc b/dlls/shell32/shell32_Tr.rc index ab9f61a6735..9617e850e61 100644 --- a/dlls/shell32/shell32_Tr.rc +++ b/dlls/shell32/shell32_Tr.rc @@ -155,6 +155,7 @@ STRINGTABLE IDS_DESKTOP "Masaüstü" IDS_MYCOMPUTER "Bilgisayarým" IDS_RECYCLEBIN_FOLDER_NAME "Çöp" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "Bü&yük Simgeler" diff --git a/dlls/shell32/shell32_Uk.rc b/dlls/shell32/shell32_Uk.rc index e3d5de53f89..eef1dc05397 100644 --- a/dlls/shell32/shell32_Uk.rc +++ b/dlls/shell32/shell32_Uk.rc @@ -141,6 +141,7 @@ STRINGTABLE { IDS_DESKTOP "Ñò³ëüíèöÿ" IDS_MYCOMPUTER "̳é Êîìï'þòåð" + IDS_CONTROLPANEL "Control Panel" /* context menus */ IDS_VIEW_LARGE "&Âåëèê³ ²êîíêè" diff --git a/dlls/shell32/shresdef.h b/dlls/shell32/shresdef.h index 24373b719ba..cb11a80dfcd 100644 --- a/dlls/shell32/shresdef.h +++ b/dlls/shell32/shresdef.h @@ -38,13 +38,14 @@ #define IDS_DESKTOP 20 #define IDS_MYCOMPUTER 21 - -#define IDS_SELECT 22 -#define IDS_OPEN 23 -#define IDS_VIEW_LARGE 24 -#define IDS_VIEW_SMALL 25 -#define IDS_VIEW_LIST 26 -#define IDS_VIEW_DETAILS 27 +#define IDS_CONTROLPANEL 22 + +#define IDS_SELECT 23 +#define IDS_OPEN 24 +#define IDS_VIEW_LARGE 25 +#define IDS_VIEW_SMALL 26 +#define IDS_VIEW_LIST 27 +#define IDS_VIEW_DETAILS 28 #define IDS_RESTART_TITLE 40 #define IDS_RESTART_PROMPT 41 diff --git a/dlls/shell32/tests/Makefile.in b/dlls/shell32/tests/Makefile.in index dd77c7c2f9d..088499f8528 100644 --- a/dlls/shell32/tests/Makefile.in +++ b/dlls/shell32/tests/Makefile.in @@ -9,7 +9,7 @@ CTESTS = \ generated.c \ shelllink.c \ shellpath.c \ - shfldr_netplaces.c \ + shfldr_special.c \ shlexec.c \ shlfileop.c \ shlfolder.c \ diff --git a/dlls/shell32/tests/shelllink.c b/dlls/shell32/tests/shelllink.c index 5cbd8bfcd71..54bb2915938 100644 --- a/dlls/shell32/tests/shelllink.c +++ b/dlls/shell32/tests/shelllink.c @@ -540,7 +540,7 @@ static void test_load_save(void) *p='\0'; /* IShellLink returns path in long form */ - pGetLongPathNameA(mypath, realpath, MAX_PATH); + if (!pGetLongPathNameA(mypath, realpath, MAX_PATH)) strcpy( realpath, mypath ); /* Overwrite the existing lnk file and point it to existing files */ desc.description="test 2"; diff --git a/dlls/shell32/tests/shellpath.c b/dlls/shell32/tests/shellpath.c index a6bbcaefba7..a1cf2d37707 100644 --- a/dlls/shell32/tests/shellpath.c +++ b/dlls/shell32/tests/shellpath.c @@ -478,11 +478,14 @@ static void testShellValues(const struct shellExpectedValues testEntries[], { BYTE type; - type = testSHGetFolderLocation(optional, testEntries[i].folder); - ok(type == testEntries[i].pidlType || optional, - "%s has type %d (0x%02x), expected %d (0x%02x)\n", - getFolderName(testEntries[i].folder), type, type, - testEntries[i].pidlType, testEntries[i].pidlType); + if (pSHGetFolderLocation) + { + type = testSHGetFolderLocation(optional, testEntries[i].folder); + ok(type == testEntries[i].pidlType || optional, + "%s has type %d (0x%02x), expected %d (0x%02x)\n", + getFolderName(testEntries[i].folder), type, type, + testEntries[i].pidlType, testEntries[i].pidlType); + } type = testSHGetSpecialFolderLocation(optional, testEntries[i].folder); ok(type == testEntries[i].pidlType || optional, "%s has type %d (0x%02x), expected %d (0x%02x)\n", @@ -576,12 +579,15 @@ static void testPersonal(void) /* The pidl may be a real folder, or a virtual directory, or a drive if the * home directory is set to the root directory of a drive. */ - type = testSHGetFolderLocation(FALSE, CSIDL_PERSONAL); - ok(type == PT_FOLDER || type == PT_GUID || type == PT_DRIVE, - "CSIDL_PERSONAL returned invalid type 0x%02x, " - "expected PT_FOLDER or PT_GUID\n", type); - if (type == PT_FOLDER) - testSHGetFolderPath(FALSE, CSIDL_PERSONAL); + if (pSHGetFolderLocation) + { + type = testSHGetFolderLocation(FALSE, CSIDL_PERSONAL); + ok(type == PT_FOLDER || type == PT_GUID || type == PT_DRIVE, + "CSIDL_PERSONAL returned invalid type 0x%02x, " + "expected PT_FOLDER or PT_GUID\n", type); + if (type == PT_FOLDER) + testSHGetFolderPath(FALSE, CSIDL_PERSONAL); + } type = testSHGetSpecialFolderLocation(FALSE, CSIDL_PERSONAL); ok(type == PT_FOLDER || type == PT_GUID || type == PT_DRIVE, "CSIDL_PERSONAL returned invalid type 0x%02x, " @@ -898,6 +904,10 @@ START_TEST(shellpath) doChild(myARGV[2]); else { + /* Report missing functions once */ + if (!pSHGetFolderLocation) + skip("SHGetFolderLocation is not available\n"); + /* first test various combinations of parameters: */ testApiParameters(); diff --git a/dlls/shell32/tests/shfldr_netplaces.c b/dlls/shell32/tests/shfldr_special.c similarity index 60% rename from dlls/shell32/tests/shfldr_netplaces.c rename to dlls/shell32/tests/shfldr_special.c index a2619f0b1b3..9e64d307733 100644 --- a/dlls/shell32/tests/shfldr_netplaces.c +++ b/dlls/shell32/tests/shfldr_special.c @@ -1,7 +1,8 @@ /* - * Tests for My Network Places shell folder + * Tests for special shell folders * * Copyright 2008 Robert Shearman for CodeWeavers + * Copyright 2008 Owen Rudge * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,6 +30,7 @@ #include "wine/test.h" +/* Tests for My Network Places */ static void test_parse_for_entire_network(void) { static const WCHAR entire_network_path[] = { @@ -56,8 +58,36 @@ static void test_parse_for_entire_network(void) ILFree(pidl); } +/* Tests for Control Panel */ +static void test_parse_for_control_panel(void) +{ + /* path of My Computer\Control Panel */ + static const WCHAR control_panel_path[] = { + ':',':','{','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','}','\\', + ':',':','{','2','1','E','C','2','0','2','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','D','-','0','8','0','0','2','B','3','0','3','0','9','D','}', 0 }; + IShellFolder *psfDesktop; + HRESULT hr; + DWORD eaten = 0xdeadbeef; + LPITEMIDLIST pidl; + DWORD attr = ~0; + DWORD expected_attr; + + hr = SHGetDesktopFolder(&psfDesktop); + ok(hr == S_OK, "SHGetDesktopFolder failed with error 0x%x\n", hr); + + hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, (LPWSTR)control_panel_path, &eaten, &pidl, &attr); + ok(hr == S_OK, "IShellFolder_ParseDisplayName failed with error 0x%x\n", hr); + todo_wine ok(eaten == 0xdeadbeef, "eaten should not have been set to %u\n", eaten); + + expected_attr = SFGAO_CANLINK | SFGAO_FOLDER | SFGAO_HASSUBFOLDER; + todo_wine ok(attr == expected_attr, "attr should be 0x%x, not 0x%x\n", expected_attr, attr); + + ILFree(pidl); +} + -START_TEST(shfldr_netplaces) +START_TEST(shfldr_special) { test_parse_for_entire_network(); + test_parse_for_control_panel(); } diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c index 950f1d7a8bc..9bb7208d626 100644 --- a/dlls/shell32/tests/shlfolder.c +++ b/dlls/shell32/tests/shlfolder.c @@ -450,21 +450,25 @@ static void test_GetDisplayName(void) /* The pidl returned through the last parameter of SetNameOf is a simple one. */ hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlLast, wszDirName, SHGDN_NORMAL, &pidlNew); ok (SUCCEEDED(hr), "SetNameOf failed! hr = %08x\n", hr); - ok (((LPITEMIDLIST)((LPBYTE)pidlNew+pidlNew->mkid.cb))->mkid.cb == 0, - "pidl returned from SetNameOf should be simple!\n"); - - /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf - * is implemented on top of SHFileOperation in WinXP. */ - hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszAbsoluteFilename, - SHGDN_FORPARSING, NULL); - ok (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED), "SetNameOf succeeded! hr = %08x\n", hr); - - /* Rename the file back to its original name. SetNameOf ignores the fact, that the - * SHGDN flags specify an absolute path. */ - hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszFileName, SHGDN_FORPARSING, NULL); - ok (SUCCEEDED(hr), "SetNameOf failed! hr = %08x\n", hr); + if(hr == S_OK) + { + ok (((LPITEMIDLIST)((LPBYTE)pidlNew+pidlNew->mkid.cb))->mkid.cb == 0, + "pidl returned from SetNameOf should be simple!\n"); + + /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf + * is implemented on top of SHFileOperation in WinXP. */ + hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszAbsoluteFilename, + SHGDN_FORPARSING, NULL); + ok (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED), "SetNameOf succeeded! hr = %08x\n", hr); + + /* Rename the file back to its original name. SetNameOf ignores the fact, that the + * SHGDN flags specify an absolute path. */ + hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszFileName, SHGDN_FORPARSING, NULL); + ok (SUCCEEDED(hr), "SetNameOf failed! hr = %08x\n", hr); + + pILFree(pidlNew); + } - pILFree(pidlNew); IShellFolder_Release(psfPersonal); } diff --git a/dlls/shlwapi/string.c b/dlls/shlwapi/string.c index 4537ac2c873..abbfdbafdae 100644 --- a/dlls/shlwapi/string.c +++ b/dlls/shlwapi/string.c @@ -511,7 +511,7 @@ LPWSTR WINAPI StrCpyNW(LPWSTR lpszStr, LPCWSTR lpszSrc, int iLen) * Internal implementation of StrStrA/StrStrIA */ static LPSTR SHLWAPI_StrStrHelperA(LPCSTR lpszStr, LPCSTR lpszSearch, - int (*pStrCmpFn)(LPCSTR,LPCSTR,size_t)) + INT (WINAPI *pStrCmpFn)(LPCSTR,LPCSTR,INT)) { size_t iLen; @@ -545,7 +545,7 @@ LPSTR WINAPI StrStrA(LPCSTR lpszStr, LPCSTR lpszSearch) { TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch)); - return SHLWAPI_StrStrHelperA(lpszStr, lpszSearch, strncmp); + return SHLWAPI_StrStrHelperA(lpszStr, lpszSearch, StrCmpNA); } /************************************************************************* @@ -650,7 +650,7 @@ LPSTR WINAPI StrStrIA(LPCSTR lpszStr, LPCSTR lpszSearch) { TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch)); - return SHLWAPI_StrStrHelperA(lpszStr, lpszSearch, strncasecmp); + return SHLWAPI_StrStrHelperA(lpszStr, lpszSearch, StrCmpNIA); } /************************************************************************* diff --git a/dlls/shlwapi/tests/path.c b/dlls/shlwapi/tests/path.c index b2d2a9ea7b1..e6b6548247d 100644 --- a/dlls/shlwapi/tests/path.c +++ b/dlls/shlwapi/tests/path.c @@ -537,9 +537,13 @@ static void test_PathCombineA(void) SetLastError(0xdeadbeef); lstrcpyA(dest, "control"); str = PathCombineA(dest, "relative\\dir", "\\one\\two\\three\\"); - ok(str == dest, "Expected str == dest, got %p\n", str); - ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str); ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); + /* Vista fails which probably makes sense as PathCombineA expects an absolute dir */ + if (str) + { + ok(str == dest, "Expected str == dest, got %p\n", str); + ok(!lstrcmp(str, "one\\two\\three\\"), "Expected one\\two\\three\\, got %s\n", str); + } /* try forward slashes */ SetLastError(0xdeadbeef); @@ -806,10 +810,8 @@ static void test_PathCanonicalizeA(void) ok(!res, "Expected failure\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); - todo_wine - { - ok(!lstrcmp(dest, "test"), "Expected test, got %s\n", dest); - } + ok(dest[0] == 0 || !lstrcmp(dest, "test"), + "Expected either an empty string (Vista) or test, got %s\n", dest); /* try an empty source */ lstrcpy(dest, "test"); diff --git a/dlls/shlwapi/tests/url.c b/dlls/shlwapi/tests/url.c index cd7a5f20286..37c0111dd55 100644 --- a/dlls/shlwapi/tests/url.c +++ b/dlls/shlwapi/tests/url.c @@ -74,6 +74,10 @@ static const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = { {"file:///c:/tests\\foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar", FALSE}, {"file:///c:/tests/foo%20bar", 0, S_OK, "file:///c:/tests/foo%20bar", FALSE}, {"file:///c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE}, + {"file://localhost/c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE}, + {"file://localhost\\c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE}, + {"file://localhost\\\\c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE}, + {"file://localhost\\c:\\tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE}, {"file://c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE}, {"file://c:/tests\\../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE}, {"file://c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\\foo bar", FALSE}, diff --git a/dlls/shlwapi/url.c b/dlls/shlwapi/url.c index 2593f9608a4..16031e879a4 100644 --- a/dlls/shlwapi/url.c +++ b/dlls/shlwapi/url.c @@ -319,6 +319,7 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, WCHAR slash = '/'; static const WCHAR wszFile[] = {'f','i','l','e',':'}; + static const WCHAR wszLocalhost[] = {'l','o','c','a','l','h','o','s','t'}; TRACE("(%s, %p, %p, 0x%08x) *pcchCanonicalized: %d\n", debugstr_w(pszUrl), pszCanonicalized, pcchCanonicalized, dwFlags, pcchCanonicalized ? *pcchCanonicalized : -1); @@ -387,6 +388,12 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, *wk2++ = *wk1++; if (*wk1 != '/') {state = 6; break;} *wk2++ = *wk1++; + if((dwFlags & URL_FILE_USE_PATHURL) && nByteLen >= sizeof(wszLocalhost) + && !memcmp(wszLocalhost, wk1, sizeof(wszLocalhost))){ + wk1 += sizeof(wszLocalhost)/sizeof(WCHAR); + while(*wk1 == '\\' && (dwFlags & URL_FILE_USE_PATHURL)) + wk1++; + } if(*wk1 == '/' && (dwFlags & URL_FILE_USE_PATHURL)) wk1++; state = 4; diff --git a/dlls/strmiids/strmiids.c b/dlls/strmiids/strmiids.c index b060ec465cf..a257a23e9a4 100644 --- a/dlls/strmiids/strmiids.c +++ b/dlls/strmiids/strmiids.c @@ -29,6 +29,8 @@ #include "objbase.h" #include "oleauto.h" #include "olectl.h" +#include "d3d9.h" + #include "initguid.h" #include "uuids.h" @@ -36,3 +38,4 @@ #include "control.h" #include "amstream.h" #include "qedit.h" +#include "vmr9.h" diff --git a/dlls/urlmon/file.c b/dlls/urlmon/file.c index d3004ac6a22..dda1dd0f811 100644 --- a/dlls/urlmon/file.c +++ b/dlls/urlmon/file.c @@ -109,6 +109,10 @@ static HRESULT WINAPI FileProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl TRACE("(%p)->(%s %p %p %08x %d)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved); + if(!szUrl || lstrlenW(szUrl) < sizeof(wszFile)/sizeof(WCHAR) + || memcmp(szUrl, wszFile, sizeof(wszFile))) + return E_INVALIDARG; + memset(&bindinfo, 0, sizeof(bindinfo)); bindinfo.cbSize = sizeof(BINDINFO); hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo); @@ -119,13 +123,6 @@ static HRESULT WINAPI FileProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl ReleaseBindInfo(&bindinfo); - if(!szUrl || !*szUrl) - return E_INVALIDARG; - - if(lstrlenW(szUrl) < sizeof(wszFile)/sizeof(WCHAR) - || memcmp(szUrl, wszFile, sizeof(wszFile))) - return MK_E_SYNTAX; - len = lstrlenW(szUrl)+16; url = heap_alloc(len*sizeof(WCHAR)); hres = CoInternetParseUrl(szUrl, PARSE_ENCODE, 0, url, len, &len, 0); diff --git a/dlls/urlmon/tests/protocol.c b/dlls/urlmon/tests/protocol.c index 7aff61705dd..bc666ebbbb4 100644 --- a/dlls/urlmon/tests/protocol.c +++ b/dlls/urlmon/tests/protocol.c @@ -1342,8 +1342,10 @@ static void test_file_protocol_fail(void) SET_EXPECT(GetBindInfo); expect_hrResult = MK_E_SYNTAX; hres = IInternetProtocol_Start(protocol, wszIndexHtml, &protocol_sink, &bind_info, 0, 0); - ok(hres == MK_E_SYNTAX, "Start failed: %08x, expected MK_E_SYNTAX\n", hres); - CHECK_CALLED(GetBindInfo); + ok(hres == MK_E_SYNTAX || + hres == E_INVALIDARG, + "Start failed: %08x, expected MK_E_SYNTAX or E_INVALIDARG\n", hres); + CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */ SET_EXPECT(GetBindInfo); if(!(bindf & BINDF_FROMURLMON)) @@ -1387,12 +1389,12 @@ static void test_file_protocol_fail(void) SET_EXPECT(GetBindInfo); hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0); ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres); - CHECK_CALLED(GetBindInfo); + CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */ SET_EXPECT(GetBindInfo); hres = IInternetProtocol_Start(protocol, emptyW, &protocol_sink, &bind_info, 0, 0); ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres); - CHECK_CALLED(GetBindInfo); + CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */ IInternetProtocol_Release(protocol); } diff --git a/dlls/user32/class.c b/dlls/user32/class.c index 1ca50f583be..1f4b7b5028d 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -421,6 +421,7 @@ void CLASS_RegisterBuiltinClasses(void) register_builtin( &LISTBOX_builtin_class ); register_builtin( &MDICLIENT_builtin_class ); register_builtin( &MENU_builtin_class ); + register_builtin( &MESSAGE_builtin_class ); register_builtin( &SCROLL_builtin_class ); register_builtin( &STATIC_builtin_class ); diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h index dbec147b17b..a16d166bf38 100644 --- a/dlls/user32/controls.h +++ b/dlls/user32/controls.h @@ -53,6 +53,7 @@ extern const struct builtin_class_descr ICONTITLE_builtin_class DECLSPEC_HIDDEN; extern const struct builtin_class_descr LISTBOX_builtin_class DECLSPEC_HIDDEN; extern const struct builtin_class_descr MDICLIENT_builtin_class DECLSPEC_HIDDEN; extern const struct builtin_class_descr MENU_builtin_class DECLSPEC_HIDDEN; +extern const struct builtin_class_descr MESSAGE_builtin_class DECLSPEC_HIDDEN; extern const struct builtin_class_descr SCROLL_builtin_class DECLSPEC_HIDDEN; extern const struct builtin_class_descr STATIC_builtin_class DECLSPEC_HIDDEN; diff --git a/dlls/user32/dde_client.c b/dlls/user32/dde_client.c index 31a12510cbe..83bc9fb0ffe 100644 --- a/dlls/user32/dde_client.c +++ b/dlls/user32/dde_client.c @@ -576,7 +576,7 @@ static HGLOBAL WDML_BuildExecuteCommand(WDML_CONV* pConv, LPCVOID pData, DWORD c { if (clientUnicode) { - memSize = WideCharToMultiByte( CP_ACP, 0, pData, cbData, NULL, 0, NULL, NULL); + memSize = WideCharToMultiByte( CP_ACP, 0, pData, cbData / sizeof(WCHAR), NULL, 0, NULL, NULL); } else { @@ -601,7 +601,7 @@ static HGLOBAL WDML_BuildExecuteCommand(WDML_CONV* pConv, LPCVOID pData, DWORD c { if (clientUnicode) { - WideCharToMultiByte( CP_ACP, 0, pData, cbData, pDst, memSize, NULL, NULL); + WideCharToMultiByte( CP_ACP, 0, pData, cbData / sizeof(WCHAR), pDst, memSize, NULL, NULL); } else { diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c index a9867c644fe..444a73dcb3d 100644 --- a/dlls/user32/dialog.c +++ b/dlls/user32/dialog.c @@ -1085,7 +1085,7 @@ BOOL WINAPI IsDialogMessageW( HWND hwndDlg, LPMSG msg ) if (CallMsgFilterW( msg, MSGF_DIALOGBOX )) return TRUE; hwndDlg = WIN_GetFullHandle( hwndDlg ); - if (hwndDlg == GetDesktopWindow()) return FALSE; + if (is_desktop_window(hwndDlg)) return FALSE; if ((hwndDlg != msg->hwnd) && !IsChild( hwndDlg, msg->hwnd )) return FALSE; hwndDlg = DIALOG_FindMsgDestination(hwndDlg); diff --git a/dlls/user32/focus.c b/dlls/user32/focus.c index 2eb14962d11..3253a870d4c 100644 --- a/dlls/user32/focus.c +++ b/dlls/user32/focus.c @@ -264,6 +264,7 @@ HWND WINAPI SetFocus( HWND hwnd ) if (style & (WS_MINIMIZE | WS_DISABLED)) return 0; parent = GetAncestor( hwndTop, GA_PARENT ); if (!parent || parent == GetDesktopWindow()) break; + if (parent == get_hwnd_message_parent()) return 0; hwndTop = parent; } diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index 88eb72f4e3f..b4c19553330 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -116,9 +116,9 @@ typedef struct { /* internal flags for menu tracking */ -#define TF_ENDMENU 0x0001 -#define TF_SUSPENDPOPUP 0x0002 -#define TF_SKIPREMOVE 0x0004 +#define TF_ENDMENU 0x10000 +#define TF_SUSPENDPOPUP 0x20000 +#define TF_SKIPREMOVE 0x40000 typedef struct { diff --git a/dlls/user32/message.c b/dlls/user32/message.c index ce18acdc23d..6588f8e7e8f 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -89,6 +89,22 @@ struct send_message_info }; +/* Message class descriptor */ +static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0}; +static LRESULT WINAPI message_winproc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); +const struct builtin_class_descr MESSAGE_builtin_class = +{ + messageW, /* name */ + 0, /* style */ + NULL, /* procA (winproc is Unicode only) */ + message_winproc, /* procW */ + 0, /* extra */ + IDC_ARROW, /* cursor */ + 0 /* brush */ +}; + + + /* flag for messages that contain pointers */ /* 32 messages per entry, messages 0..31 map to bits 0..31 */ @@ -315,6 +331,19 @@ static inline BOOL get_pending_wmchar( MSG *msg, UINT first, UINT last, BOOL rem return TRUE; } + +/*********************************************************************** + * message_winproc + * + * Window procedure for "Message" windows (HWND_MESSAGE parent). + */ +static LRESULT WINAPI message_winproc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) +{ + if (message == WM_NCCREATE) return TRUE; + return 0; /* all other messages are ignored */ +} + + /*********************************************************************** * broadcast_message_callback * @@ -1252,21 +1281,21 @@ static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPAR case WM_WINE_DESTROYWINDOW: return WIN_DestroyWindow( hwnd ); case WM_WINE_SETWINDOWPOS: - if (hwnd == GetDesktopWindow()) return 0; + if (is_desktop_window( hwnd )) return 0; return USER_SetWindowPos( (WINDOWPOS *)lparam ); case WM_WINE_SHOWWINDOW: - if (hwnd == GetDesktopWindow()) return 0; + if (is_desktop_window( hwnd )) return 0; return ShowWindow( hwnd, wparam ); case WM_WINE_SETPARENT: - if (hwnd == GetDesktopWindow()) return 0; + if (is_desktop_window( hwnd )) return 0; return (LRESULT)SetParent( hwnd, (HWND)wparam ); case WM_WINE_SETWINDOWLONG: return WIN_SetWindowLong( hwnd, (short)LOWORD(wparam), HIWORD(wparam), lparam, TRUE ); case WM_WINE_ENABLEWINDOW: - if (hwnd == GetDesktopWindow()) return 0; + if (is_desktop_window( hwnd )) return 0; return EnableWindow( hwnd, wparam ); case WM_WINE_SETACTIVEWINDOW: - if (hwnd == GetDesktopWindow()) return 0; + if (is_desktop_window( hwnd )) return 0; return (LRESULT)SetActiveWindow( (HWND)wparam ); case WM_WINE_KEYBOARD_LL_HOOK: case WM_WINE_MOUSE_LL_HOOK: diff --git a/dlls/user32/sysparams.c b/dlls/user32/sysparams.c index b2fe6276c49..6e260eac6c0 100644 --- a/dlls/user32/sysparams.c +++ b/dlls/user32/sysparams.c @@ -73,10 +73,12 @@ enum spi_index SPI_SETMOUSEHOVERWIDTH_IDX, SPI_SETMOUSEHOVERHEIGHT_IDX, SPI_SETMOUSEHOVERTIME_IDX, + SPI_SETMOUSESCROLLCHARS_IDX, SPI_SETMOUSESCROLLLINES_IDX, SPI_SETMENUSHOWDELAY_IDX, SPI_SETICONTITLELOGFONT_IDX, SPI_SETLOWPOWERACTIVE_IDX, + SPI_SETSNAPTODEFBUTTON_IDX, SPI_SETPOWEROFFACTIVE_IDX, SPI_USERPREFERENCEMASK_IDX, SPI_NONCLIENTMETRICS_IDX, @@ -166,6 +168,8 @@ static const WCHAR SPI_SETMENUDROPALIGNMENT_REGKEY1[]= {'S','o','f','t',' 'W','i','n','d','o','w','s',0}; static const WCHAR SPI_SETMENUDROPALIGNMENT_REGKEY2[]= {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p',0}; static const WCHAR SPI_SETMENUDROPALIGNMENT_VALNAME[]= {'M','e','n','u','D','r','o','p','A','l','i','g','n','m','e','n','t',0}; +static const WCHAR SPI_SETSNAPTODEFBUTTON_REGKEY[]= {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0}; +static const WCHAR SPI_SETSNAPTODEFBUTTON_VALNAME[]= {'S','n','a','p','T','o','D','e','f','a','u','l','t','B','u','t','t','o','n',0}; static const WCHAR SPI_SETDOUBLECLKWIDTH_REGKEY1[]= {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0}; static const WCHAR SPI_SETDOUBLECLKWIDTH_REGKEY2[]= {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p',0}; static const WCHAR SPI_SETDOUBLECLKWIDTH_VALNAME[]= {'D','o','u','b','l','e','C','l','i','c','k','W','i','d','t','h',0}; @@ -206,6 +210,8 @@ static const WCHAR SPI_SETMOUSEHOVERHEIGHT_REGKEY[]= {'C','o','n','t',' static const WCHAR SPI_SETMOUSEHOVERHEIGHT_VALNAME[]= {'M','o','u','s','e','H','o','v','e','r','H','e','i','g','h','t',0}; static const WCHAR SPI_SETMOUSEHOVERTIME_REGKEY[]= {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','M','o','u','s','e',0}; static const WCHAR SPI_SETMOUSEHOVERTIME_VALNAME[]= {'M','o','u','s','e','H','o','v','e','r','T','i','m','e',0}; +static const WCHAR SPI_SETMOUSESCROLLCHARS_REGKEY[]= {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p',0}; +static const WCHAR SPI_SETMOUSESCROLLCHARS_VALNAME[]= {'W','h','e','e','l','S','c','r','o','l','l','C','h','a','r','s',0}; static const WCHAR SPI_SETMOUSESCROLLLINES_REGKEY[]= {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p',0}; static const WCHAR SPI_SETMOUSESCROLLLINES_VALNAME[]= {'W','h','e','e','l','S','c','r','o','l','l','L','i','n','e','s',0}; static const WCHAR SPI_SETMENUSHOWDELAY_REGKEY[]= {'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\','D','e','s','k','t','o','p',0}; @@ -290,6 +296,7 @@ static BOOL screen_reader = FALSE; static UINT mouse_hover_width = 4; static UINT mouse_hover_height = 4; static UINT mouse_hover_time = 400; +static UINT mouse_scroll_chars = 3; static UINT mouse_scroll_lines = 3; static UINT menu_show_delay = 400; static UINT menu_drop_alignment = 0; @@ -298,6 +305,7 @@ static UINT font_smoothing = 0; /* 0x01 for 95/98/NT, 0x02 for 98/ME/2k/XP */ static BOOL lowpoweractive = FALSE; static BOOL poweroffactive = FALSE; static BOOL show_sounds = FALSE; +static BOOL snap_to_default_button = FALSE; static BOOL swap_buttons = FALSE; static UINT caret_width = 1; static BYTE user_prefs[4]; @@ -2016,8 +2024,20 @@ BOOL WINAPI SystemParametersInfoW( UINT uiAction, UINT uiParam, WINE_SPI_FIXME(SPI_SETMOUSETRAILS); /* 93 WINVER >= 0x400 */ WINE_SPI_FIXME(SPI_GETMOUSETRAILS); /* 94 WINVER >= 0x400 */ - WINE_SPI_FIXME(SPI_GETSNAPTODEFBUTTON); /* 95 WINVER >= 0x400 */ - WINE_SPI_FIXME(SPI_SETSNAPTODEFBUTTON); /* 96 WINVER >= 0x400 */ + + case SPI_GETSNAPTODEFBUTTON: /* 95 WINVER >= 0x400 */ + ret = get_bool_param( SPI_SETSNAPTODEFBUTTON_IDX, + SPI_SETSNAPTODEFBUTTON_REGKEY, + SPI_SETSNAPTODEFBUTTON_VALNAME, + &snap_to_default_button, pvParam ); + break; + + case SPI_SETSNAPTODEFBUTTON: /* 96 WINVER >= 0x400 */ + ret = set_bool_param( SPI_SETSNAPTODEFBUTTON_IDX, + SPI_SETSNAPTODEFBUTTON_REGKEY, + SPI_SETSNAPTODEFBUTTON_VALNAME, + &snap_to_default_button, uiParam, fWinIni ); + break; case SPI_SETSCREENSAVERRUNNING: ret = set_bool_param( SPI_SETSCREENSAVERRUNNING_IDX, @@ -2096,6 +2116,20 @@ BOOL WINAPI SystemParametersInfoW( UINT uiAction, UINT uiParam, &menu_show_delay, uiParam, fWinIni ); break; + case SPI_GETWHEELSCROLLCHARS: /* 108 _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */ + ret = get_uint_param( SPI_SETMOUSESCROLLCHARS_IDX, + SPI_SETMOUSESCROLLCHARS_REGKEY, + SPI_SETMOUSESCROLLCHARS_VALNAME, + &mouse_scroll_chars, pvParam ); + break; + + case SPI_SETWHEELSCROLLCHARS: /* 109 _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */ + ret = set_uint_param( SPI_SETMOUSESCROLLCHARS_IDX, + SPI_SETMOUSESCROLLCHARS_REGKEY, + SPI_SETMOUSESCROLLCHARS_VALNAME, + &mouse_scroll_chars, uiParam, fWinIni ); + break; + WINE_SPI_FIXME(SPI_GETSHOWIMEUI); /* 110 _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */ WINE_SPI_FIXME(SPI_SETSHOWIMEUI); /* 111 _WIN32_WINNT >= 0x400 || _WIN32_WINDOW > 0x400 */ diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 962aa5c745a..dfb610843c4 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -460,6 +460,48 @@ static const struct message WmShowMaxOverlappedSeq[] = { { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 } }; +/* ShowWindow(SW_RESTORE) for a not visible maximized overlapped window */ +static const struct message WmShowRestoreMaxOverlappedSeq[] = { + { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, + { WM_GETTEXT, sent|optional }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, + { WM_GETMINMAXINFO, sent|defwinproc }, + { WM_NCCALCSIZE, sent|wparam, TRUE }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, + { WM_MOVE, sent|defwinproc }, + { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, + { 0 } +}; +/* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */ +static const struct message WmShowRestoreMinOverlappedSeq[] = { + { HCBT_MINMAX, hook|lparam, 0, SW_RESTORE }, + { WM_QUERYOPEN, sent|optional }, + { WM_GETTEXT, sent|optional }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED|SWP_NOCOPYBITS }, + { WM_GETMINMAXINFO, sent|defwinproc }, + { WM_NCCALCSIZE, sent|wparam, TRUE }, + { HCBT_ACTIVATE, hook }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_ACTIVATEAPP, sent|wparam, 1 }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_STATECHANGED|SWP_FRAMECHANGED|SWP_NOCOPYBITS }, + { WM_MOVE, sent|defwinproc }, + { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, + { WM_ACTIVATE, sent|wparam, 1 }, + { 0 } +}; /* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */ static const struct message WmShowMinOverlappedSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, @@ -1521,7 +1563,9 @@ static int log_all_parent_messages; /* user32 functions */ static HWND (WINAPI *pGetAncestor)(HWND,UINT); +static BOOL (WINAPI *pGetMenuInfo)(HMENU,LPCMENUINFO); static void (WINAPI *pNotifyWinEvent)(DWORD, HWND, LONG, LONG); +static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO); static HWINEVENTHOOK (WINAPI *pSetWinEventHook)(DWORD, DWORD, HMODULE, WINEVENTPROC, DWORD, DWORD, DWORD); static BOOL (WINAPI *pTrackMouseEvent)(TRACKMOUSEEVENT*); static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK); @@ -1540,7 +1584,9 @@ static void init_procs(void) } GET_PROC(user32, GetAncestor) + GET_PROC(user32, GetMenuInfo) GET_PROC(user32, NotifyWinEvent) + GET_PROC(user32, SetMenuInfo) GET_PROC(user32, SetWinEventHook) GET_PROC(user32, TrackMouseEvent) GET_PROC(user32, UnhookWinEvent) @@ -4108,7 +4154,7 @@ static void test_messages(void) ok(GetActiveWindow() == hwnd, "window should be active\n"); ok(GetFocus() == hwnd, "window should have input focus\n"); ShowWindow(hwnd, SW_HIDE); - ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", TRUE); + ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE); ShowWindow(hwnd, SW_SHOW); ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE); @@ -4120,7 +4166,7 @@ static void test_messages(void) ok_sequence(WmShowMaxOverlappedSeq, "ShowWindow(SW_SHOWMAXIMIZED):overlapped", TRUE); ShowWindow(hwnd, SW_RESTORE); - /* FIXME: add ok_sequence() here */ + ok_sequence(WmShowRestoreMaxOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", FALSE); flush_sequence(); ShowWindow(hwnd, SW_MINIMIZE); @@ -4128,7 +4174,7 @@ static void test_messages(void) flush_sequence(); ShowWindow(hwnd, SW_RESTORE); - /* FIXME: add ok_sequence() here */ + ok_sequence(WmShowRestoreMinOverlappedSeq, "ShowWindow(SW_RESTORE):overlapped", TRUE); flush_sequence(); ShowWindow(hwnd, SW_SHOW); @@ -9935,6 +9981,158 @@ static void test_nullCallback(void) DestroyWindow(hwnd); } +/* SetActiveWindow( 0 ) hwnd visible */ +static const struct message SetActiveWindowSeq0[] = +{ + { HCBT_ACTIVATE, hook }, + { WM_NCACTIVATE, sent|wparam, 0 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_KILLFOCUS, sent|defwinproc }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { WM_SETFOCUS, sent|defwinproc }, + { 0 } +}; +/* SetActiveWindow( hwnd ) hwnd visible */ +static const struct message SetActiveWindowSeq1[] = +{ + { 0 } +}; +/* SetActiveWindow( popup ) hwnd visible, popup visible */ +static const struct message SetActiveWindowSeq2[] = +{ + { HCBT_ACTIVATE, hook }, + { WM_NCACTIVATE, sent|wparam, 0 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, + { WM_NCPAINT, sent|optional }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_KILLFOCUS, sent|defwinproc }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { WM_SETFOCUS, sent|defwinproc }, + { 0 } +}; + +/* SetActiveWindow( hwnd ) hwnd not visible */ +static const struct message SetActiveWindowSeq3[] = +{ + { HCBT_ACTIVATE, hook }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_ACTIVATEAPP, sent|wparam, 1 }, + { WM_ACTIVATEAPP, sent|wparam, 1 }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { WM_SETFOCUS, sent|defwinproc }, + { 0 } +}; +/* SetActiveWindow( popup ) hwnd not visible, popup not visible */ +static const struct message SetActiveWindowSeq4[] = +{ + { HCBT_ACTIVATE, hook }, + { WM_NCACTIVATE, sent|wparam, 0 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_KILLFOCUS, sent|defwinproc }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 1 }, + { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { WM_SETFOCUS, sent|defwinproc }, + { 0 } +}; + + +static void test_SetActiveWindow(void) +{ + HWND hwnd, popup, ret; + + hwnd = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + + popup = CreateWindowExA(0, "TestWindowClass", "Test SetActiveWindow", + WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_POPUP, + 100, 100, 200, 200, hwnd, 0, 0, NULL); + + ok(hwnd != 0, "Failed to create overlapped window\n"); + flush_sequence(); + + ok(popup != 0, "Failed to create popup window\n"); + flush_sequence(); + + trace("SetActiveWindow(0)\n"); + ret = SetActiveWindow(0); + ok( ret == popup, "Failed to SetActiveWindow(0)\n"); + ok_sequence(SetActiveWindowSeq0, "SetActiveWindow(0)", TRUE); + flush_sequence(); + + trace("SetActiveWindow(hwnd), hwnd visible\n"); + ret = SetActiveWindow(hwnd); + todo_wine + { + ok( ret == hwnd, "Failed to SetActiveWindow(hwnd), hwnd visible\n"); + } + ok_sequence(SetActiveWindowSeq1, "SetActiveWindow(hwnd), hwnd visible", TRUE); + flush_sequence(); + + trace("SetActiveWindow(popup), hwnd visible, popup visble\n"); + ret = SetActiveWindow(popup); + ok( ret == hwnd, "Failed to SetActiveWindow(popup), popup visble\n"); + ok_sequence(SetActiveWindowSeq2, "SetActiveWindow(popup), hwnd visible, popup visble", TRUE); + flush_sequence(); + + ShowWindow(hwnd, SW_HIDE); + ShowWindow(popup, SW_HIDE); + flush_sequence(); + + trace("SetActiveWindow(hwnd), hwnd not visible\n"); + ret = SetActiveWindow(hwnd); + ok( ret == NULL, "Failed to SetActiveWindow(hwnd), hwnd not visible\n"); + ok_sequence(SetActiveWindowSeq3, "SetActiveWindow(hwnd), hwnd not visible", TRUE); + flush_sequence(); + + trace("SetActiveWindow(popup), hwnd not visible, popup not visble\n"); + ret = SetActiveWindow(popup); + ok( ret == hwnd, "Failed to SetActiveWindow(popup)\n"); + ok_sequence(SetActiveWindowSeq4, "SetActiveWindow(popup), hwnd not visible, popup not visble", TRUE); + flush_sequence(); + + trace("done\n"); + + DestroyWindow(hwnd); +} + static const struct message SetForegroundWindowSeq[] = { { WM_NCACTIVATE, sent|wparam, 0 }, @@ -10574,7 +10772,7 @@ static void set_menu_style(HMENU hmenu, DWORD style) mi.fMask = MIM_STYLE; mi.dwStyle = style; SetLastError(0xdeadbeef); - ret = SetMenuInfo(hmenu, &mi); + ret = pSetMenuInfo(hmenu, &mi); ok(ret, "SetMenuInfo error %u\n", GetLastError()); } @@ -10587,7 +10785,7 @@ static DWORD get_menu_style(HMENU hmenu) mi.fMask = MIM_STYLE; mi.dwStyle = 0; SetLastError(0xdeadbeef); - ret = GetMenuInfo(hmenu, &mi); + ret = pGetMenuInfo(hmenu, &mi); ok(ret, "GetMenuInfo error %u\n", GetLastError()); return mi.dwStyle; @@ -10601,6 +10799,11 @@ static void test_menu_messages(void) HWND hwnd; DWORD style; + if (!pGetMenuInfo || !pSetMenuInfo) + { + skip("GetMenuInfo and/or SetMenuInfo are not available\n"); + return; + } cls.style = 0; cls.lpfnWndProc = parent_menu_proc; cls.cbClsExtra = 0; @@ -10675,7 +10878,7 @@ static void test_menu_messages(void) set_menu_style(hmenu, 0); style = get_menu_style(hmenu); - ok(style == 0, "expected MNS_NOTIFYBYPOS, got %u\n", style); + ok(style == 0, "expected 0, got %u\n", style); hmenu_popup = GetSubMenu(hmenu, 0); ok(hmenu_popup != 0, "GetSubMenu returned 0 for submenu 0\n"); @@ -10779,6 +10982,7 @@ START_TEST(msg) test_SendMessageTimeout(); test_edit_messages(); test_quit_message(); + test_SetActiveWindow(); if (!pTrackMouseEvent) skip("TrackMouseEvent is not available\n"); @@ -10789,9 +10993,12 @@ START_TEST(msg) test_sys_menu(); test_dialog_messages(); test_nullCallback(); - test_SetForegroundWindow(); test_dbcs_wm_char(); test_menu_messages(); + /* keep it the last test, under Windows it tends to break the tests + * which rely on active/foreground windows being correct. + */ + test_SetForegroundWindow(); UnhookWindowsHookEx(hCBT_hook); if (pUnhookWinEvent) diff --git a/dlls/user32/tests/sysparams.c b/dlls/user32/tests/sysparams.c index af6c7315e34..f899dab143a 100644 --- a/dlls/user32/tests/sysparams.c +++ b/dlls/user32/tests/sysparams.c @@ -129,12 +129,16 @@ static HDC hdc; #define SPI_SETPOWEROFFACTIVE_VALNAME "PowerOffActive" #define SPI_SETDRAGFULLWINDOWS_REGKEY "Control Panel\\Desktop" #define SPI_SETDRAGFULLWINDOWS_VALNAME "DragFullWindows" +#define SPI_SETSNAPTODEFBUTTON_REGKEY "Control Panel\\Mouse" +#define SPI_SETSNAPTODEFBUTTON_VALNAME "SnapToDefaultButton" #define SPI_SETMOUSEHOVERWIDTH_REGKEY "Control Panel\\Mouse" #define SPI_SETMOUSEHOVERWIDTH_VALNAME "MouseHoverWidth" #define SPI_SETMOUSEHOVERHEIGHT_REGKEY "Control Panel\\Mouse" #define SPI_SETMOUSEHOVERHEIGHT_VALNAME "MouseHoverHeight" #define SPI_SETMOUSEHOVERTIME_REGKEY "Control Panel\\Mouse" #define SPI_SETMOUSEHOVERTIME_VALNAME "MouseHoverTime" +#define SPI_SETMOUSESCROLLCHARS_REGKEY "Control Panel\\Desktop" +#define SPI_SETMOUSESCROLLCHARS_VALNAME "WheelScrollChars" #define SPI_SETMOUSESCROLLLINES_REGKEY "Control Panel\\Desktop" #define SPI_SETMOUSESCROLLLINES_VALNAME "WheelScrollLines" #define SPI_SETMENUSHOWDELAY_REGKEY "Control Panel\\Desktop" @@ -1966,6 +1970,40 @@ static void test_SPI_SETPOWEROFFACTIVE( void ) /* 86 */ ok(rc!=0,"***warning*** failed to restore the original value: rc=%d err=%d\n",rc,GetLastError()); } +static void test_SPI_SETSNAPTODEFBUTTON( void ) /* 95 */ +{ + BOOL rc; + BOOL old_b; + const UINT vals[]={TRUE,FALSE}; + unsigned int i; + + trace("testing SPI_{GET,SET}SNAPTODEFBUTTON\n"); + SetLastError(0xdeadbeef); + rc=SystemParametersInfoA( SPI_GETSNAPTODEFBUTTON, 0, &old_b, 0 ); + if (!test_error_msg(rc,"SPI_GETSNAPTODEFBUTTON")) + return; + + for (i=0;idesktop ); - CloseHandle( get_user_thread_info()->server_queue ); - HeapFree( GetProcessHeap(), 0, get_user_thread_info()->wmchar_data ); + if (thread_info->top_window) WIN_DestroyThreadWindows( thread_info->top_window ); + if (thread_info->msg_window) WIN_DestroyThreadWindows( thread_info->msg_window ); + CloseHandle( thread_info->server_queue ); + HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data ); exiting_thread_id = 0; } diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 6483d663db0..b16d605efd6 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -204,9 +204,10 @@ struct user_thread_info HCURSOR cursor; /* Current cursor */ INT cursor_count; /* Cursor show count */ UINT active_hooks; /* Bitmap of active hooks */ - HWND desktop; /* Desktop window */ + HWND top_window; /* Desktop window */ + HWND msg_window; /* HWND_MESSAGE parent window */ - ULONG pad[10]; /* Available for more data */ + ULONG pad[9]; /* Available for more data */ }; struct hook_extra_info diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 1824a52b346..9a97a3a70e3 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -150,10 +150,17 @@ static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name, { struct user_thread_info *thread_info = get_user_thread_info(); - if (!thread_info->desktop) thread_info->desktop = full_parent ? full_parent : handle; - else assert( full_parent == thread_info->desktop ); - if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop )) - ERR( "failed to create desktop window\n" ); + if (name == (LPCWSTR)DESKTOP_CLASS_ATOM) + { + if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle; + else assert( full_parent == thread_info->top_window ); + if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->top_window )) + ERR( "failed to create desktop window\n" ); + } + else /* HWND_MESSAGE parent */ + { + if (!thread_info->msg_window && !full_parent) thread_info->msg_window = handle; + } } USER_Lock(); @@ -350,6 +357,42 @@ static void get_server_window_text( HWND hwnd, LPWSTR text, INT count ) } +/******************************************************************* + * get_hwnd_message_parent + * + * Return the parent for HWND_MESSAGE windows. + */ +HWND get_hwnd_message_parent(void) +{ + struct user_thread_info *thread_info = get_user_thread_info(); + + if (!thread_info->msg_window) GetDesktopWindow(); /* trigger creation */ + return thread_info->msg_window; +} + + +/******************************************************************* + * is_desktop_window + * + * Check if window is the desktop or the HWND_MESSAGE top parent. + */ +BOOL is_desktop_window( HWND hwnd ) +{ + struct user_thread_info *thread_info = get_user_thread_info(); + + if (!hwnd) return FALSE; + if (hwnd == thread_info->top_window) return TRUE; + if (hwnd == thread_info->msg_window) return TRUE; + + if (!HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) + { + if (LOWORD(thread_info->top_window) == LOWORD(hwnd)) return TRUE; + if (LOWORD(thread_info->msg_window) == LOWORD(hwnd)) return TRUE; + } + return FALSE; +} + + /*********************************************************************** * WIN_GetPtr * @@ -372,11 +415,7 @@ WND *WIN_GetPtr( HWND hwnd ) return ptr; ptr = NULL; } - else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow())) - { - if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP; - else ptr = NULL; - } + else if (is_desktop_window( hwnd )) ptr = WND_DESKTOP; else ptr = WND_OTHER_PROCESS; USER_Unlock(); return ptr; @@ -433,7 +472,11 @@ HWND WIN_Handle32( HWND16 hwnd16 ) if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd; - if (ptr == WND_DESKTOP) return GetDesktopWindow(); + if (ptr == WND_DESKTOP) + { + if (LOWORD(hwnd) == LOWORD(GetDesktopWindow())) return GetDesktopWindow(); + else return get_hwnd_message_parent(); + } if (ptr != WND_OTHER_PROCESS) { @@ -548,8 +591,16 @@ BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient ) { RECT rect; rect.left = rect.top = 0; - rect.right = GetSystemMetrics(SM_CXSCREEN); - rect.bottom = GetSystemMetrics(SM_CYSCREEN); + if (hwnd == get_hwnd_message_parent()) + { + rect.right = 100; + rect.bottom = 100; + } + else + { + rect.right = GetSystemMetrics(SM_CXSCREEN); + rect.bottom = GetSystemMetrics(SM_CYSCREEN); + } if (rectWindow) *rectWindow = rect; if (rectClient) *rectClient = rect; } @@ -962,11 +1013,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags if (cs->hwndParent == HWND_MESSAGE) { - /* native ole32.OleInitialize uses HWND_MESSAGE to create the - * message window (style: WS_POPUP|WS_DISABLED) - */ - FIXME("Parent is HWND_MESSAGE\n"); - parent = GetDesktopWindow(); + cs->hwndParent = parent = get_hwnd_message_parent(); } else if (cs->hwndParent) { @@ -978,13 +1025,17 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags } else { + static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0}; + if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) { WARN("No parent for child window\n" ); SetLastError(ERROR_TLW_WITH_WSCHILD); return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */ } - if (className != (LPCWSTR)DESKTOP_CLASS_ATOM) /* are we creating the desktop itself? */ + /* are we creating the desktop or HWND_MESSAGE parent itself? */ + if (className != (LPCWSTR)DESKTOP_CLASS_ATOM && + (IS_INTRESOURCE(className) || strcmpiW( className, messageW ))) parent = GetDesktopWindow(); } @@ -1410,7 +1461,7 @@ BOOL WINAPI DestroyWindow( HWND hwnd ) { BOOL is_child; - if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow())) + if (!(hwnd = WIN_IsCurrentThread( hwnd )) || is_desktop_window( hwnd )) { SetLastError( ERROR_ACCESS_DENIED ); return FALSE; @@ -1527,7 +1578,9 @@ HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR t int i = 0, len = 0; WCHAR *buffer = NULL; - if (!parent) parent = GetDesktopWindow(); + if (!parent && child) parent = GetDesktopWindow(); + else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent(); + if (title) { len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */ @@ -1620,16 +1673,20 @@ HWND WINAPI GetDesktopWindow(void) { struct user_thread_info *thread_info = get_user_thread_info(); - if (thread_info->desktop) return thread_info->desktop; + if (thread_info->top_window) return thread_info->top_window; SERVER_START_REQ( get_desktop_window ) { req->force = 0; - if (!wine_server_call( req )) thread_info->desktop = reply->handle; + if (!wine_server_call( req )) + { + thread_info->top_window = reply->top_window; + thread_info->msg_window = reply->msg_window; + } } SERVER_END_REQ; - if (!thread_info->desktop) + if (!thread_info->top_window) { USEROBJECTFLAGS flags; if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags, @@ -1664,15 +1721,19 @@ HWND WINAPI GetDesktopWindow(void) SERVER_START_REQ( get_desktop_window ) { req->force = 1; - if (!wine_server_call( req )) thread_info->desktop = reply->handle; + if (!wine_server_call( req )) + { + thread_info->top_window = reply->top_window; + thread_info->msg_window = reply->msg_window; + } } SERVER_END_REQ; } - if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop )) + if (!thread_info->top_window || !USER_Driver->pCreateDesktopWindow( thread_info->top_window )) ERR( "failed to create desktop window\n" ); - return thread_info->desktop; + return thread_info->top_window; } @@ -2580,7 +2641,8 @@ HWND WINAPI GetAncestor( HWND hwnd, UINT type ) break; case GA_ROOTOWNER: - if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0; + if (is_desktop_window( hwnd )) return 0; + ret = WIN_GetFullHandle( hwnd ); for (;;) { HWND parent = GetParent( ret ); @@ -2611,6 +2673,7 @@ HWND WINAPI SetParent( HWND hwnd, HWND parent ) } if (!parent) parent = GetDesktopWindow(); + else if (parent == HWND_MESSAGE) parent = get_hwnd_message_parent(); else parent = WIN_GetFullHandle( parent ); if (!IsWindow( parent )) @@ -2695,11 +2758,11 @@ BOOL WINAPI IsWindowVisible( HWND hwnd ) if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE; if (!(list = list_window_parents( hwnd ))) return TRUE; - if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */ + if (list[0]) { for (i = 0; list[i+1]; i++) if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break; - retval = !list[i+1]; + retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */ } HeapFree( GetProcessHeap(), 0, list ); return retval; @@ -2724,12 +2787,12 @@ BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon ) if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE; if (!(list = list_window_parents( hwnd ))) return TRUE; - if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */ + if (list[0]) { for (i = 0; list[i+1]; i++) if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE) break; - retval = !list[i+1]; + retval = !list[i+1] && (list[i] == GetDesktopWindow()); /* top message window isn't visible */ } HeapFree( GetProcessHeap(), 0, list ); return retval; @@ -2879,6 +2942,11 @@ HWND WINAPI GetLastActivePopup( HWND hwnd ) */ HWND *WIN_ListChildren( HWND hwnd ) { + if (!hwnd) + { + SetLastError( ERROR_INVALID_WINDOW_HANDLE ); + return NULL; + } return list_window_children( 0, hwnd, NULL, 0 ); } diff --git a/dlls/user32/win.h b/dlls/user32/win.h index 5e7a67ed2e6..bc024f4547f 100644 --- a/dlls/user32/win.h +++ b/dlls/user32/win.h @@ -76,6 +76,8 @@ typedef struct tagWND #define WIN_NEEDS_SHOW_OWNEDPOPUP 0x0080 /* WM_SHOWWINDOW:SC_SHOW must be sent in the next ShowOwnedPopup call */ /* Window functions */ +extern HWND get_hwnd_message_parent(void) DECLSPEC_HIDDEN; +extern BOOL is_desktop_window( HWND hwnd ) DECLSPEC_HIDDEN; extern WND *WIN_GetPtr( HWND hwnd ) DECLSPEC_HIDDEN; extern HWND WIN_Handle32( HWND16 hwnd16 ) DECLSPEC_HIDDEN; extern HWND WIN_IsCurrentProcess( HWND hwnd ) DECLSPEC_HIDDEN; diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 621f89a25a5..7398152a7a8 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -1073,6 +1073,7 @@ static BOOL show_window( HWND hwnd, INT cmd ) if (parent == GetDesktopWindow()) parent = 0; SetFocus(parent); } + return wasVisible; } if (IsIconic(hwnd)) WINPOS_ShowIconTitle( hwnd, TRUE ); @@ -2099,7 +2100,7 @@ HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter, hdwp, hwnd, hwndAfter, x, y, cx, cy, flags); hwnd = WIN_GetFullHandle( hwnd ); - if (hwnd == GetDesktopWindow()) return 0; + if (is_desktop_window( hwnd )) return 0; if (!(pDWP = USER_HEAP_LIN_ADDR( hdwp ))) return 0; diff --git a/dlls/user32/winstation.c b/dlls/user32/winstation.c index abee28656dc..57ce952f034 100644 --- a/dlls/user32/winstation.c +++ b/dlls/user32/winstation.c @@ -395,7 +395,12 @@ BOOL WINAPI SetThreadDesktop( HDESK handle ) ret = !wine_server_call_err( req ); } SERVER_END_REQ; - if (ret) get_user_thread_info()->desktop = 0; /* reset the desktop window */ + if (ret) /* reset the desktop windows */ + { + struct user_thread_info *thread_info = get_user_thread_info(); + thread_info->top_window = 0; + thread_info->msg_window = 0; + } return ret; } diff --git a/dlls/winealsa.drv/mixer.c b/dlls/winealsa.drv/mixer.c index cc38f8f0642..ee67eef018d 100644 --- a/dlls/winealsa.drv/mixer.c +++ b/dlls/winealsa.drv/mixer.c @@ -762,7 +762,7 @@ static DWORD MIX_Open(UINT wDevID, LPMIXEROPENDESC desc, DWORD_PTR flags) static DWORD MIX_Close(UINT wDevID) { - int x; + int x = 0; mixer *mmixer = MIX_GetMix(wDevID); if (!mmixer) return MMSYSERR_BADDEVICEID; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index ce8b63b5bdd..982963aaae4 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -2285,6 +2285,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D /* Destroy the depth blt resources, they will be invalid after the reset. Also free shader * private data, it might contain opengl pointers */ + if(This->depth_blt_texture) { + glDeleteTextures(1, &This->depth_blt_texture); + This->depth_blt_texture = 0; + } This->shader_backend->shader_destroy_depth_blt(iface); This->shader_backend->shader_free_private(iface); diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index ace619964e8..acb147e4a91 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -2321,7 +2321,7 @@ static BOOL CheckTextureCapability(UINT Adapter, WINED3DFORMAT CheckFormat) /* Floating point formats */ case WINED3DFMT_R16F: case WINED3DFMT_A16B16G16R16F: - if(GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) { + if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) { TRACE_(d3d_caps)("[OK]\n"); return TRUE; } @@ -2952,13 +2952,13 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DPMISCCAPS_CLIPTLVERTS | WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS | WINED3DPMISCCAPS_MASKZ | - WINED3DPMISCCAPS_BLENDOP; + WINED3DPMISCCAPS_BLENDOP | + WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING; /* TODO: WINED3DPMISCCAPS_NULLREFERENCE WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS WINED3DPMISCCAPS_FOGANDSPECULARALPHA WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS - WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING WINED3DPMISCCAPS_FOGVERTEXCLAMPED */ if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) @@ -3597,22 +3597,23 @@ struct driver_version_information { }; static const struct driver_version_information driver_version_table[] = { - /* Nvidia drivers. Geforce FX and newer cards are supported by the current driver */ + /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (177.x)*/ + /* GeforceFX support is up to 173.x, Geforce2MX/3/4 upto 96.x, TNT/Geforce1/2 upto 71.x */ /* Note that version numbers >100 lets say 123.45 use >= x.y.11.2345 and not x.y.10.12345 */ - {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 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, 7, 15, 11, 7341 }, + {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, 7, 15, 11, 7341 }, {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, 7, 15, 11, 7341 }, {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, 7, 15, 11, 7341 }, diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index 7333edf9b10..f314ee938f4 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -732,6 +732,7 @@ static void depth_blt(IWineD3DDevice *iface, GLuint texture) { glDisable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); + glDepthMask(GL_TRUE); glBlendFunc(GL_ZERO, GL_ONE); GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB)); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 672997780a5..1f5df189d06 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -2834,8 +2834,8 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, semantic *semantics_in, sema if (!semantics_out) { /* Save gl_FrontColor & gl_FrontSecondaryColor before overwriting them. */ - shader_addline(buffer, "vec4 front_color = gl_FrontColor;"); - shader_addline(buffer, "vec4 front_secondary_color = gl_FrontSecondaryColor;"); + shader_addline(buffer, "vec4 front_color = gl_FrontColor;\n"); + shader_addline(buffer, "vec4 front_secondary_color = gl_FrontSecondaryColor;\n"); } for(i = 0; i < MAX_REG_INPUT; i++) { diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index d2883da2e55..5a0271740ff 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -168,7 +168,7 @@ static const GlPixelFormatDescTemplate gl_formats_template[] = { {WINED3DFMT_G16R16F ,0 ,0 , 0, 0 ,0 ,WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET }, {WINED3DFMT_A16B16G16R16F ,GL_RGBA16F_ARB ,GL_RGBA16F_ARB , 0, GL_RGBA ,GL_HALF_FLOAT_ARB - ,WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET }, + ,WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET }, /* Palettized formats */ {WINED3DFMT_A8P8, 0 ,0 , 0, 0 ,0 ,0 }, diff --git a/dlls/wineps.drv/init.c b/dlls/wineps.drv/init.c index 5b85c45dd10..61e31d8778e 100644 --- a/dlls/wineps.drv/init.c +++ b/dlls/wineps.drv/init.c @@ -538,7 +538,6 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name) char* ppdFileName = NULL; HKEY hkey; BOOL using_default_devmode = FALSE; - static CHAR paper_size[] = "Paper Size"; TRACE("'%s'\n", name); @@ -606,12 +605,11 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name) } #endif if (!ppdFileName) { - static CHAR ppd_file[] = "PPD File"; - - res = GetPrinterDataA(hPrinter, ppd_file, NULL, NULL, 0, &needed); + res = GetPrinterDataExA(hPrinter, "PrinterDriverData", "PPD File", NULL, NULL, 0, &needed); if ((res==ERROR_SUCCESS) || (res==ERROR_MORE_DATA)) { ppdFileName=HeapAlloc(PSDRV_Heap, 0, needed); - res = GetPrinterDataA(hPrinter, ppd_file, &ppdType, (LPBYTE)ppdFileName, needed, &needed); + res = GetPrinterDataExA(hPrinter, "PrinterDriverData", "PPD File", &ppdType, + (LPBYTE)ppdFileName, needed, &needed); } } /* Look for a ppd file for this printer in the config file. @@ -706,8 +704,8 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name) * the Devmode structure, but Wine doesn't currently provide a convenient * way to configure printers. */ - res = GetPrinterDataA (hPrinter, paper_size, NULL, (LPBYTE) &dwPaperSize, - sizeof (DWORD), &needed); + res = GetPrinterDataExA(hPrinter, "PrinterDriverData", "Paper Size", NULL, + (LPBYTE)&dwPaperSize, sizeof(DWORD), &needed); if (res == ERROR_SUCCESS) pi->Devmode->dmPublic.u1.s1.dmPaperSize = (SHORT) dwPaperSize; else if (res == ERROR_FILE_NOT_FOUND) diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index d2ff6feb13d..8bbc252fe4f 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -909,7 +909,7 @@ static int BITBLT_GetSrcAreaStretch( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE * pixels to Windows colors. */ static int BITBLT_GetSrcArea( X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst, - Pixmap pixmap, GC gc, INT xSrc, INT ySrc, RECT *visRectSrc ) + Pixmap pixmap, GC gc, RECT *visRectSrc ) { XImage *imageSrc, *imageDst; register INT x, y; @@ -1443,7 +1443,7 @@ static BOOL BITBLT_InternalStretchBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT &visRectSrc, &visRectDst ); else BITBLT_GetSrcArea( physDevSrc, physDevDst, pixmaps[SRC], tmpGC, - xSrc, ySrc, &visRectSrc ); + &visRectSrc ); } if (useDst) BITBLT_GetDstArea( physDevDst, pixmaps[DST], tmpGC, &visRectDst ); diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c index af5ff9d0534..8a35a0bd3cd 100644 --- a/dlls/winex11.drv/clipboard.c +++ b/dlls/winex11.drv/clipboard.c @@ -110,9 +110,9 @@ typedef struct struct tagWINE_CLIPDATA; /* Forward */ -typedef HANDLE (*DRVEXPORTFUNC)(Window requestor, Atom aTarget, Atom rprop, +typedef HANDLE (*DRVEXPORTFUNC)(Display *display, Window requestor, Atom aTarget, Atom rprop, struct tagWINE_CLIPDATA* lpData, LPDWORD lpBytes); -typedef HANDLE (*DRVIMPORTFUNC)(Window w, Atom prop); +typedef HANDLE (*DRVIMPORTFUNC)(Display *d, Window w, Atom prop); typedef struct tagWINE_CLIPFORMAT { UINT wFormatID; @@ -147,37 +147,37 @@ static Atom selectionCacheSrc = XA_PRIMARY; /* The selection source from whic void X11DRV_EmptyClipboard(BOOL keepunowned); void X11DRV_EndClipboardUpdate(void); -static HANDLE X11DRV_CLIPBOARD_ImportClipboardData(Window w, Atom prop); -static HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(Window w, Atom prop); -static HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(Window w, Atom prop); -static HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Window w, Atom prop); -static HANDLE X11DRV_CLIPBOARD_ImportXAString(Window w, Atom prop); -static HANDLE X11DRV_CLIPBOARD_ImportUTF8(Window w, Atom prop); -static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Window w, Atom prop); -static HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Window requestor, Atom aTarget, +static HANDLE X11DRV_CLIPBOARD_ImportClipboardData(Display *d, Window w, Atom prop); +static HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(Display *d, Window w, Atom prop); +static HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(Display *d, Window w, Atom prop); +static HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Display *d, Window w, Atom prop); +static HANDLE X11DRV_CLIPBOARD_ImportXAString(Display *d, Window w, Atom prop); +static HANDLE X11DRV_CLIPBOARD_ImportUTF8(Display *d, Window w, Atom prop); +static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Display *d, Window w, Atom prop); +static HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Display *display, Window requestor, Atom aTarget, Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes); -static HANDLE X11DRV_CLIPBOARD_ExportString(Window requestor, Atom aTarget, +static HANDLE X11DRV_CLIPBOARD_ExportString(Display *display, Window requestor, Atom aTarget, Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes); -static HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget, +static HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Display *display, Window requestor, Atom aTarget, Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes); -static HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget, +static HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Display *display, Window requestor, Atom aTarget, Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes); -static HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget, +static HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Display *display, Window requestor, Atom aTarget, Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes); static WINE_CLIPFORMAT *X11DRV_CLIPBOARD_InsertClipboardFormat(LPCWSTR FormatName, Atom prop); -static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID); +static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(Display *display, UINT wFormatID); static void X11DRV_CLIPBOARD_FreeData(LPWINE_CLIPDATA lpData); static BOOL X11DRV_CLIPBOARD_IsSelectionOwner(void); -static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo); -static BOOL X11DRV_CLIPBOARD_ReadSelectionData(LPWINE_CLIPDATA lpData); -static BOOL X11DRV_CLIPBOARD_ReadProperty(Window w, Atom prop, +static int X11DRV_CLIPBOARD_QueryAvailableData(Display *display, LPCLIPBOARDINFO lpcbinfo); +static BOOL X11DRV_CLIPBOARD_ReadSelectionData(Display *display, LPWINE_CLIPDATA lpData); +static BOOL X11DRV_CLIPBOARD_ReadProperty(Display *display, Window w, Atom prop, unsigned char** data, unsigned long* datasize); -static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData); +static BOOL X11DRV_CLIPBOARD_RenderFormat(Display *display, LPWINE_CLIPDATA lpData); static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDWORD lpcbytes, BOOL out); static BOOL X11DRV_CLIPBOARD_SynthesizeData(UINT wFormatID); -static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData); -static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(void); -static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(void); +static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(Display *display, LPWINE_CLIPDATA lpData); +static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(Display *display); +static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(Display *display); static void X11DRV_HandleSelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple ); /* Clipboard formats @@ -317,7 +317,8 @@ static UINT wSeqNo = 0; static Window thread_selection_wnd(void) { - Window w = x11drv_thread_data()->selection_wnd; + struct x11drv_thread_data *thread_data = x11drv_init_thread_data(); + Window w = thread_data->selection_wnd; if (!w) { @@ -327,12 +328,12 @@ static Window thread_selection_wnd(void) ButtonPressMask | ButtonReleaseMask | EnterWindowMask); wine_tsx11_lock(); - w = XCreateWindow(thread_display(), root_window, 0, 0, 1, 1, 0, screen_depth, + w = XCreateWindow(thread_data->display, root_window, 0, 0, 1, 1, 0, screen_depth, InputOutput, CopyFromParent, CWEventMask, &attr); wine_tsx11_unlock(); if (w) - x11drv_thread_data()->selection_wnd = w; + thread_data->selection_wnd = w; else FIXME("Failed to create window. Fetching selection data will fail.\n"); } @@ -364,11 +365,14 @@ static void intern_atoms(void) int i, count, len; char **names; Atom *atoms; + Display *display; for (format = ClipFormats, count = 0; format; format = format->NextFormat) if (!format->drvData) count++; if (!count) return; + display = thread_init_display(); + names = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*names) ); atoms = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*atoms) ); @@ -381,7 +385,7 @@ static void intern_atoms(void) } wine_tsx11_lock(); - XInternAtoms( thread_display(), names, count, False, atoms ); + XInternAtoms( display, names, count, False, atoms ); wine_tsx11_unlock(); for (format = ClipFormats, i = 0; format; format = format->NextFormat) { @@ -753,7 +757,7 @@ static BOOL X11DRV_CLIPBOARD_UpdateCache(LPCLIPBOARDINFO lpcbinfo) { X11DRV_EmptyClipboard(TRUE); - if (X11DRV_CLIPBOARD_QueryAvailableData(lpcbinfo) < 0) + if (X11DRV_CLIPBOARD_QueryAvailableData(thread_init_display(), lpcbinfo) < 0) { ERR("Failed to cache clipboard data owned by another process.\n"); bret = FALSE; @@ -774,7 +778,7 @@ static BOOL X11DRV_CLIPBOARD_UpdateCache(LPCLIPBOARDINFO lpcbinfo) /************************************************************************** * X11DRV_CLIPBOARD_RenderFormat */ -static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData) +static BOOL X11DRV_CLIPBOARD_RenderFormat(Display *display, LPWINE_CLIPDATA lpData) { BOOL bret = TRUE; @@ -785,10 +789,10 @@ static BOOL X11DRV_CLIPBOARD_RenderFormat(LPWINE_CLIPDATA lpData) return bret; /* Already rendered */ if (lpData->wFlags & CF_FLAG_SYNTHESIZED) - bret = X11DRV_CLIPBOARD_RenderSynthesizedFormat(lpData); + bret = X11DRV_CLIPBOARD_RenderSynthesizedFormat(display, lpData); else if (!X11DRV_CLIPBOARD_IsSelectionOwner()) { - if (!X11DRV_CLIPBOARD_ReadSelectionData(lpData)) + if (!X11DRV_CLIPBOARD_ReadSelectionData(display, lpData)) { ERR("Failed to cache clipboard data owned by another process. Format=%d\n", lpData->wFormatID); @@ -878,7 +882,7 @@ static INT CLIPBOARD_ConvertText(WORD src_fmt, void const *src, INT src_size, /************************************************************************** * X11DRV_CLIPBOARD_RenderSynthesizedFormat */ -static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData) +static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(Display *display, LPWINE_CLIPDATA lpData) { BOOL bret = FALSE; @@ -889,17 +893,17 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData) UINT wFormatID = lpData->wFormatID; if (wFormatID == CF_UNICODETEXT || wFormatID == CF_TEXT || wFormatID == CF_OEMTEXT) - bret = X11DRV_CLIPBOARD_RenderSynthesizedText(wFormatID); + bret = X11DRV_CLIPBOARD_RenderSynthesizedText(display, wFormatID); else { switch (wFormatID) { case CF_DIB: - bret = X11DRV_CLIPBOARD_RenderSynthesizedDIB(); + bret = X11DRV_CLIPBOARD_RenderSynthesizedDIB( display ); break; case CF_BITMAP: - bret = X11DRV_CLIPBOARD_RenderSynthesizedBitmap(); + bret = X11DRV_CLIPBOARD_RenderSynthesizedBitmap( display ); break; case CF_ENHMETAFILE: @@ -925,7 +929,7 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedFormat(LPWINE_CLIPDATA lpData) * * Renders synthesized text */ -static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID) +static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(Display *display, UINT wFormatID) { LPCSTR lpstrS; LPSTR lpstrT; @@ -961,7 +965,7 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID) return FALSE; /* Ask the clipboard owner to render the source text if necessary */ - if (!lpSource->hData32 && !X11DRV_CLIPBOARD_RenderFormat(lpSource)) + if (!lpSource->hData32 && !X11DRV_CLIPBOARD_RenderFormat(display, lpSource)) return FALSE; if (lpSource->hData32) @@ -1025,7 +1029,7 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedText(UINT wFormatID) * * Renders synthesized DIB */ -static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(void) +static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(Display *display) { BOOL bret = FALSE; LPWINE_CLIPDATA lpSource = NULL; @@ -1041,7 +1045,7 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(void) (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32)) { /* Render source if required */ - if (lpSource->hData32 || X11DRV_CLIPBOARD_RenderFormat(lpSource)) + if (lpSource->hData32 || X11DRV_CLIPBOARD_RenderFormat(display, lpSource)) { HDC hdc; HGLOBAL hData32; @@ -1067,7 +1071,7 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedDIB(void) * * Renders synthesized bitmap */ -static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(void) +static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(Display *display) { BOOL bret = FALSE; LPWINE_CLIPDATA lpSource = NULL; @@ -1083,7 +1087,7 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(void) (!(lpSource->wFlags & CF_FLAG_SYNTHESIZED) || lpSource->hData32)) { /* Render source if required */ - if (lpSource->hData32 || X11DRV_CLIPBOARD_RenderFormat(lpSource)) + if (lpSource->hData32 || X11DRV_CLIPBOARD_RenderFormat(display, lpSource)) { HDC hdc; HBITMAP hData32; @@ -1120,7 +1124,7 @@ static BOOL X11DRV_CLIPBOARD_RenderSynthesizedBitmap(void) * * Import XA_STRING, converting the string to CF_TEXT. */ -HANDLE X11DRV_CLIPBOARD_ImportXAString(Window w, Atom prop) +HANDLE X11DRV_CLIPBOARD_ImportXAString(Display *display, Window w, Atom prop) { LPBYTE lpdata; unsigned long cbytes; @@ -1128,7 +1132,7 @@ HANDLE X11DRV_CLIPBOARD_ImportXAString(Window w, Atom prop) unsigned long i, inlcount = 0; HANDLE hText = 0; - if (!X11DRV_CLIPBOARD_ReadProperty(w, prop, &lpdata, &cbytes)) + if (!X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes)) return 0; for (i = 0; i <= cbytes; i++) @@ -1164,7 +1168,7 @@ HANDLE X11DRV_CLIPBOARD_ImportXAString(Window w, Atom prop) * * Import XA_STRING, converting the string to CF_UNICODE. */ -HANDLE X11DRV_CLIPBOARD_ImportUTF8(Window w, Atom prop) +HANDLE X11DRV_CLIPBOARD_ImportUTF8(Display *display, Window w, Atom prop) { LPBYTE lpdata; unsigned long cbytes; @@ -1172,7 +1176,7 @@ HANDLE X11DRV_CLIPBOARD_ImportUTF8(Window w, Atom prop) unsigned long i, inlcount = 0; HANDLE hUnicodeText = 0; - if (!X11DRV_CLIPBOARD_ReadProperty(w, prop, &lpdata, &cbytes)) + if (!X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes)) return 0; for (i = 0; i <= cbytes; i++) @@ -1218,9 +1222,8 @@ HANDLE X11DRV_CLIPBOARD_ImportUTF8(Window w, Atom prop) * * Import COMPOUND_TEXT to CF_UNICODE */ -static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Window w, Atom prop) +static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Display *display, Window w, Atom prop) { - Display *display = thread_display(); int i, j; char** srcstr; int count, lcount; @@ -1285,7 +1288,7 @@ static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Window w, Atom prop) * * Import XA_PIXMAP, converting the image to CF_DIB. */ -HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Window w, Atom prop) +HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Display *display, Window w, Atom prop) { HWND hwnd; HDC hdc; @@ -1294,7 +1297,7 @@ HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Window w, Atom prop) Pixmap *pPixmap; HANDLE hClipData = 0; - if (X11DRV_CLIPBOARD_ReadProperty(w, prop, &lpdata, &cbytes)) + if (X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes)) { pPixmap = (Pixmap *) lpdata; @@ -1317,13 +1320,13 @@ HANDLE X11DRV_CLIPBOARD_ImportXAPIXMAP(Window w, Atom prop) * * Import MetaFilePict. */ -HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(Window w, Atom prop) +HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(Display *display, Window w, Atom prop) { LPBYTE lpdata; unsigned long cbytes; HANDLE hClipData = 0; - if (X11DRV_CLIPBOARD_ReadProperty(w, prop, &lpdata, &cbytes)) + if (X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes)) { if (cbytes) hClipData = X11DRV_CLIPBOARD_SerializeMetafile(CF_METAFILEPICT, (HANDLE)lpdata, (LPDWORD)&cbytes, FALSE); @@ -1341,13 +1344,13 @@ HANDLE X11DRV_CLIPBOARD_ImportMetaFilePict(Window w, Atom prop) * * Import EnhMetaFile. */ -HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(Window w, Atom prop) +HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(Display *display, Window w, Atom prop) { LPBYTE lpdata; unsigned long cbytes; HANDLE hClipData = 0; - if (X11DRV_CLIPBOARD_ReadProperty(w, prop, &lpdata, &cbytes)) + if (X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes)) { if (cbytes) hClipData = X11DRV_CLIPBOARD_SerializeMetafile(CF_ENHMETAFILE, (HANDLE)lpdata, (LPDWORD)&cbytes, FALSE); @@ -1365,14 +1368,14 @@ HANDLE X11DRV_CLIPBOARD_ImportEnhMetaFile(Window w, Atom prop) * * Generic import clipboard data routine. */ -HANDLE X11DRV_CLIPBOARD_ImportClipboardData(Window w, Atom prop) +HANDLE X11DRV_CLIPBOARD_ImportClipboardData(Display *display, Window w, Atom prop) { LPVOID lpClipData; LPBYTE lpdata; unsigned long cbytes; HANDLE hClipData = 0; - if (X11DRV_CLIPBOARD_ReadProperty(w, prop, &lpdata, &cbytes)) + if (X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &lpdata, &cbytes)) { if (cbytes) { @@ -1406,8 +1409,8 @@ HANDLE X11DRV_CLIPBOARD_ImportClipboardData(Window w, Atom prop) * * Generic export clipboard data routine. */ -HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Window requestor, Atom aTarget, - Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes) +HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Display *display, Window requestor, Atom aTarget, + Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes) { LPVOID lpClipData; UINT datasize = 0; @@ -1415,7 +1418,7 @@ HANDLE X11DRV_CLIPBOARD_ExportClipboardData(Window requestor, Atom aTarget, *lpBytes = 0; /* Assume failure */ - if (!X11DRV_CLIPBOARD_RenderFormat(lpData)) + if (!X11DRV_CLIPBOARD_RenderFormat(display, lpData)) ERR("Failed to export %d format\n", lpData->wFormatID); else { @@ -1537,10 +1540,9 @@ done: * Export CF_UNICODE to COMPOUND_TEXT * Helper function for X11DRV_CLIPBOARD_ExportString. */ -static HANDLE X11DRV_CLIPBOARD_ExportCompoundText(Window requestor, Atom aTarget, Atom rprop, +static HANDLE X11DRV_CLIPBOARD_ExportCompoundText(Display *display, Window requestor, Atom aTarget, Atom rprop, LPWINE_CLIPDATA lpData, LPDWORD lpBytes) { - Display *display = thread_display(); char* lpstr = 0; XTextProperty prop; XICCEncodingStyle style; @@ -1592,15 +1594,15 @@ static HANDLE X11DRV_CLIPBOARD_ExportCompoundText(Window requestor, Atom aTarget * * Export string */ -HANDLE X11DRV_CLIPBOARD_ExportString(Window requestor, Atom aTarget, Atom rprop, - LPWINE_CLIPDATA lpData, LPDWORD lpBytes) +HANDLE X11DRV_CLIPBOARD_ExportString(Display *display, Window requestor, Atom aTarget, Atom rprop, + LPWINE_CLIPDATA lpData, LPDWORD lpBytes) { - if (X11DRV_CLIPBOARD_RenderFormat(lpData)) + if (X11DRV_CLIPBOARD_RenderFormat(display, lpData)) { if (aTarget == XA_STRING) return X11DRV_CLIPBOARD_ExportXAString(lpData, lpBytes); else if (aTarget == x11drv_atom(COMPOUND_TEXT) || aTarget == x11drv_atom(TEXT)) - return X11DRV_CLIPBOARD_ExportCompoundText(requestor, aTarget, + return X11DRV_CLIPBOARD_ExportCompoundText(display, requestor, aTarget, rprop, lpData, lpBytes); else { @@ -1620,14 +1622,14 @@ HANDLE X11DRV_CLIPBOARD_ExportString(Window requestor, Atom aTarget, Atom rprop, * * Export CF_DIB to XA_PIXMAP. */ -HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget, Atom rprop, +HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Display *display, Window requestor, Atom aTarget, Atom rprop, LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) { HDC hdc; HANDLE hData; unsigned char* lpData; - if (!X11DRV_CLIPBOARD_RenderFormat(lpdata)) + if (!X11DRV_CLIPBOARD_RenderFormat(display, lpdata)) { ERR("Failed to export %d format\n", lpdata->wFormatID); return 0; @@ -1658,10 +1660,10 @@ HANDLE X11DRV_CLIPBOARD_ExportXAPIXMAP(Window requestor, Atom aTarget, Atom rpro * * Export MetaFilePict. */ -HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget, Atom rprop, - LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) +HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Display *display, Window requestor, Atom aTarget, Atom rprop, + LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) { - if (!X11DRV_CLIPBOARD_RenderFormat(lpdata)) + if (!X11DRV_CLIPBOARD_RenderFormat(display, lpdata)) { ERR("Failed to export %d format\n", lpdata->wFormatID); return 0; @@ -1676,10 +1678,10 @@ HANDLE X11DRV_CLIPBOARD_ExportMetaFilePict(Window requestor, Atom aTarget, Atom * * Export EnhMetaFile. */ -HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Window requestor, Atom aTarget, Atom rprop, - LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) +HANDLE X11DRV_CLIPBOARD_ExportEnhMetaFile(Display *display, Window requestor, Atom aTarget, Atom rprop, + LPWINE_CLIPDATA lpdata, LPDWORD lpBytes) { - if (!X11DRV_CLIPBOARD_RenderFormat(lpdata)) + if (!X11DRV_CLIPBOARD_RenderFormat(display, lpdata)) { ERR("Failed to export %d format\n", lpdata->wFormatID); return 0; @@ -1822,9 +1824,8 @@ static VOID X11DRV_CLIPBOARD_InsertSelectionProperties(Display *display, Atom* p * This queries the selection owner for the TARGETS property and saves all * reported property types. */ -static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo) +static int X11DRV_CLIPBOARD_QueryAvailableData(Display *display, LPCLIPBOARDINFO lpcbinfo) { - Display *display = thread_display(); XEvent xe; Atom atype=AnyPropertyType; int aformat; @@ -1942,9 +1943,8 @@ static int X11DRV_CLIPBOARD_QueryAvailableData(LPCLIPBOARDINFO lpcbinfo) * We always get the data from the selection client each time, * since we have no way of determining if the data in our cache is stale. */ -static BOOL X11DRV_CLIPBOARD_ReadSelectionData(LPWINE_CLIPDATA lpData) +static BOOL X11DRV_CLIPBOARD_ReadSelectionData(Display *display, LPWINE_CLIPDATA lpData) { - Display *display = thread_display(); Bool res; DWORD i; XEvent xe; @@ -1995,7 +1995,7 @@ static BOOL X11DRV_CLIPBOARD_ReadSelectionData(LPWINE_CLIPDATA lpData) * into WINE's clipboard cache and converting the * data format if necessary. */ - HANDLE hData = lpData->lpFormat->lpDrvImportFunc(xe.xselection.requestor, + HANDLE hData = lpData->lpFormat->lpDrvImportFunc(display, xe.xselection.requestor, xe.xselection.property); bRet = X11DRV_CLIPBOARD_InsertClipboardData(lpData->wFormatID, 0, hData, 0, lpData->lpFormat, TRUE); @@ -2020,10 +2020,9 @@ static BOOL X11DRV_CLIPBOARD_ReadSelectionData(LPWINE_CLIPDATA lpData) * X11DRV_CLIPBOARD_ReadProperty * Reads the contents of the X selection property. */ -static BOOL X11DRV_CLIPBOARD_ReadProperty(Window w, Atom prop, +static BOOL X11DRV_CLIPBOARD_ReadProperty(Display *display, Window w, Atom prop, unsigned char** data, unsigned long* datasize) { - Display *display = thread_display(); Atom atype = AnyPropertyType; int aformat; unsigned long pos = 0, nitems, remain, count; @@ -2161,10 +2160,8 @@ static HANDLE X11DRV_CLIPBOARD_SerializeMetafile(INT wformat, HANDLE hdata, LPDW * * Release XA_CLIPBOARD and XA_PRIMARY in response to a SelectionClear event. */ -static void X11DRV_CLIPBOARD_ReleaseSelection(Atom selType, Window w, HWND hwnd, Time time) +static void X11DRV_CLIPBOARD_ReleaseSelection(Display *display, Atom selType, Window w, HWND hwnd, Time time) { - Display *display = thread_display(); - /* w is the window that lost the selection */ TRACE("event->window = %08x (selectionWindow = %08x) selectionAcquired=0x%08x\n", @@ -2302,7 +2299,7 @@ int X11DRV_AcquireClipboard(HWND hWndClipWindow) { DWORD procid; Window owner; - Display *display = thread_display(); + Display *display; TRACE(" %p\n", hWndClipWindow); @@ -2331,6 +2328,7 @@ int X11DRV_AcquireClipboard(HWND hWndClipWindow) } owner = thread_selection_wnd(); + display = thread_display(); wine_tsx11_lock(); @@ -2514,7 +2512,7 @@ BOOL X11DRV_GetClipboardData(UINT wFormat, HANDLE16* phData16, HANDLE* phData32) if ((lpRender = X11DRV_CLIPBOARD_LookupData(wFormat))) { if ( !lpRender->hData32 ) - X11DRV_CLIPBOARD_RenderFormat(lpRender); + X11DRV_CLIPBOARD_RenderFormat(thread_init_display(), lpRender); /* Convert between 32 -> 16 bit data, if necessary */ if (lpRender->hData32 && !lpRender->hData16) @@ -2983,7 +2981,7 @@ static void X11DRV_HandleSelectionRequest( HWND hWnd, XSelectionRequestEvent *ev { unsigned char* lpClipData; DWORD cBytes; - HANDLE hClipData = lpFormat->lpDrvExportFunc(request, event->target, + HANDLE hClipData = lpFormat->lpDrvExportFunc(display, request, event->target, rprop, lpData, &cBytes); if (hClipData && (lpClipData = GlobalLock(hClipData))) @@ -3039,5 +3037,6 @@ void X11DRV_SelectionClear( HWND hWnd, XEvent *xev ) { XSelectionClearEvent *event = &xev->xselectionclear; if (event->selection == XA_PRIMARY || event->selection == x11drv_atom(CLIPBOARD)) - X11DRV_CLIPBOARD_ReleaseSelection( event->selection, event->window, hWnd, event->time ); + X11DRV_CLIPBOARD_ReleaseSelection( event->display, event->selection, + event->window, hWnd, event->time ); } diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index edf096192dd..c8d01aa8184 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -155,7 +155,7 @@ Window X11DRV_create_desktop( UINT width, UINT height ) { XSetWindowAttributes win_attr; Window win; - Display *display = thread_display(); + Display *display = thread_init_display(); wine_tsx11_lock(); diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 764e4dad8ca..5b26b71e921 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -441,7 +441,7 @@ static inline BOOL can_activate_window( HWND hwnd ) /********************************************************************** * set_focus */ -static void set_focus( HWND hwnd, Time time ) +static void set_focus( Display *display, HWND hwnd, Time time ) { HWND focus; Window win; @@ -457,7 +457,7 @@ static void set_focus( HWND hwnd, Time time ) { TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time ); wine_tsx11_lock(); - XSetInputFocus( thread_display(), win, RevertToParent, time ); + XSetInputFocus( display, win, RevertToParent, time ); wine_tsx11_unlock(); } } @@ -532,7 +532,7 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event ) MAKELONG(HTCAPTION,WM_LBUTTONDOWN) ); if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) { - set_focus( hwnd, event_time ); + set_focus( event->display, hwnd, event_time ); return; } } @@ -541,7 +541,7 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event ) if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT ); if (!hwnd) hwnd = GetActiveWindow(); if (!hwnd) hwnd = last_focus; - if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time ); + if (hwnd && can_activate_window(hwnd)) set_focus( event->display, hwnd, event_time ); } else if (protocol == x11drv_atom(_NET_WM_PING)) { @@ -599,7 +599,7 @@ static void X11DRV_FocusIn( HWND hwnd, XEvent *xev ) if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT ); if (!hwnd) hwnd = GetActiveWindow(); if (!hwnd) hwnd = x11drv_thread_data()->last_focus; - if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime ); + if (hwnd && can_activate_window(hwnd)) set_focus( event->display, hwnd, CurrentTime ); } else SetForegroundWindow( hwnd ); } @@ -639,10 +639,10 @@ static void X11DRV_FocusOut( HWND hwnd, XEvent *xev ) getting the focus is a Wine window */ wine_tsx11_lock(); - XGetInputFocus( thread_display(), &focus_win, &revert ); + XGetInputFocus( event->display, &focus_win, &revert ); if (focus_win) { - if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0) + if (XFindContext( event->display, focus_win, winContext, (char **)&hwnd_tmp ) != 0) focus_win = 0; } wine_tsx11_unlock(); diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index 7d3d7eecec0..92c13f0b168 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1942,7 +1942,7 @@ void X11DRV_MappingNotify( HWND dummy, XEvent *event ) wine_tsx11_lock(); XRefreshKeyboardMapping(&event->xmapping); wine_tsx11_unlock(); - X11DRV_InitKeyboard( thread_display() ); + X11DRV_InitKeyboard( event->xmapping.display ); hwnd = GetFocus(); if (!hwnd) hwnd = GetActiveWindow(); @@ -1958,7 +1958,7 @@ void X11DRV_MappingNotify( HWND dummy, XEvent *event ) */ SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl) { - Display *display = thread_display(); + Display *display = thread_init_display(); KeyCode keycode; KeySym keysym; int i, index; @@ -2050,7 +2050,7 @@ SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl) */ UINT X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl) { - Display *display = thread_display(); + Display *display = thread_init_display(); #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; } @@ -2193,6 +2193,7 @@ UINT X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl) */ INT X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize) { + Display *display = thread_init_display(); int vkey, ansi, scanCode; KeyCode keyc; int keyi; @@ -2265,7 +2266,7 @@ INT X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize) { wine_tsx11_lock(); keyc = (KeyCode) keyi; - keys = XKeycodeToKeysym(thread_display(), keyc, 0); + keys = XKeycodeToKeysym(display, keyc, 0); name = XKeysymToString(keys); wine_tsx11_unlock(); TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n", @@ -2385,7 +2386,7 @@ static char KEYBOARD_MapDeadKeysym(KeySym keysym) INT X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState, LPWSTR bufW, int bufW_size, UINT flags, HKL hkl) { - Display *display = thread_display(); + Display *display = thread_init_display(); XKeyEvent e; KeySym keysym = 0; INT ret; @@ -2643,6 +2644,6 @@ found: void X11DRV_Beep(void) { wine_tsx11_lock(); - XBell(thread_display(), 0); + XBell(gdi_display, 0); wine_tsx11_unlock(); } diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index bf42765b6eb..0c1082af99b 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -930,7 +930,7 @@ static Cursor create_cursor( Display *display, const cursor_t *ptr ) */ void X11DRV_SetCursor( const cursor_t *cursor_object ) { - struct x11drv_thread_data *data = x11drv_thread_data(); + struct x11drv_thread_data *data = x11drv_init_thread_data(); Cursor cursor; if (cursor_object) @@ -967,7 +967,7 @@ void X11DRV_SetCursor( const cursor_t *cursor_object ) */ BOOL X11DRV_SetCursorPos( INT x, INT y ) { - Display *display = thread_display(); + Display *display = thread_init_display(); POINT pt; TRACE( "warping to (%d,%d)\n", x, y ); @@ -996,7 +996,7 @@ BOOL X11DRV_SetCursorPos( INT x, INT y ) */ BOOL X11DRV_GetCursorPos(LPPOINT pos) { - Display *display = thread_display(); + Display *display = thread_init_display(); Window root, child; int rootX, rootY, winX, winY; unsigned int xstate; diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index b6e88ea1db6..23f53d6f027 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -356,6 +356,7 @@ static BOOL has_opengl(void) static int init_done; static void *opengl_handle; + char buffer[200]; int error_base, event_base; if (init_done) return (opengl_handle != NULL); @@ -363,86 +364,93 @@ static BOOL has_opengl(void) /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and include all dependencies */ - opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, NULL, 0); - if (opengl_handle == NULL) return FALSE; - - pglXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0); - if (pglXGetProcAddressARB == NULL) { - ERR("could not find glXGetProcAddressARB in libGL.\n"); + opengl_handle = wine_dlopen(SONAME_LIBGL, RTLD_NOW|RTLD_GLOBAL, buffer, sizeof(buffer)); + if (opengl_handle == NULL) + { + ERR( "Failed to load libGL: %s\n", buffer ); + ERR( "OpenGL support is disabled.\n"); return FALSE; } -#define LOAD_FUNCPTR(f) if((p##f = (void*)pglXGetProcAddressARB((const unsigned char*)#f)) == NULL) goto sym_not_found; -/* GLX 1.0 */ -LOAD_FUNCPTR(glXChooseVisual) -LOAD_FUNCPTR(glXCopyContext) -LOAD_FUNCPTR(glXCreateContext) -LOAD_FUNCPTR(glXCreateGLXPixmap) -LOAD_FUNCPTR(glXGetCurrentContext) -LOAD_FUNCPTR(glXGetCurrentDrawable) -LOAD_FUNCPTR(glXDestroyContext) -LOAD_FUNCPTR(glXDestroyGLXPixmap) -LOAD_FUNCPTR(glXGetConfig) -LOAD_FUNCPTR(glXIsDirect) -LOAD_FUNCPTR(glXMakeCurrent) -LOAD_FUNCPTR(glXSwapBuffers) -LOAD_FUNCPTR(glXQueryExtension) -LOAD_FUNCPTR(glXQueryVersion) -LOAD_FUNCPTR(glXUseXFont) - -/* GLX 1.1 */ -LOAD_FUNCPTR(glXGetClientString) -LOAD_FUNCPTR(glXQueryExtensionsString) -LOAD_FUNCPTR(glXQueryServerString) - -/* GLX 1.3 */ -LOAD_FUNCPTR(glXCreatePbuffer) -LOAD_FUNCPTR(glXCreateNewContext) -LOAD_FUNCPTR(glXDestroyPbuffer) -LOAD_FUNCPTR(glXMakeContextCurrent) -LOAD_FUNCPTR(glXGetCurrentReadDrawable) -LOAD_FUNCPTR(glXGetFBConfigs) - -/* Standard OpenGL calls */ -LOAD_FUNCPTR(glBindTexture) -LOAD_FUNCPTR(glBitmap) -LOAD_FUNCPTR(glCopyTexSubImage1D) -LOAD_FUNCPTR(glCopyTexImage2D) -LOAD_FUNCPTR(glCopyTexSubImage2D) -LOAD_FUNCPTR(glDrawBuffer) -LOAD_FUNCPTR(glEndList) -LOAD_FUNCPTR(glGetError) -LOAD_FUNCPTR(glGetIntegerv) -LOAD_FUNCPTR(glGetString) -LOAD_FUNCPTR(glNewList) -LOAD_FUNCPTR(glPixelStorei) -LOAD_FUNCPTR(glReadPixels) -LOAD_FUNCPTR(glTexImage2D) -LOAD_FUNCPTR(glFinish) -LOAD_FUNCPTR(glFlush) + pglXGetProcAddressARB = wine_dlsym(opengl_handle, "glXGetProcAddressARB", NULL, 0); + if (pglXGetProcAddressARB == NULL) { + ERR("Could not find glXGetProcAddressARB in libGL, disabling OpenGL.\n"); + goto failed; + } + +#define LOAD_FUNCPTR(f) do if((p##f = (void*)pglXGetProcAddressARB((const unsigned char*)#f)) == NULL) \ + { \ + ERR( "%s not found in libGL, disabling OpenGL.\n", #f ); \ + goto failed; \ + } while(0) + + /* GLX 1.0 */ + LOAD_FUNCPTR(glXChooseVisual); + LOAD_FUNCPTR(glXCopyContext); + LOAD_FUNCPTR(glXCreateContext); + LOAD_FUNCPTR(glXCreateGLXPixmap); + LOAD_FUNCPTR(glXGetCurrentContext); + LOAD_FUNCPTR(glXGetCurrentDrawable); + LOAD_FUNCPTR(glXDestroyContext); + LOAD_FUNCPTR(glXDestroyGLXPixmap); + LOAD_FUNCPTR(glXGetConfig); + LOAD_FUNCPTR(glXIsDirect); + LOAD_FUNCPTR(glXMakeCurrent); + LOAD_FUNCPTR(glXSwapBuffers); + LOAD_FUNCPTR(glXQueryExtension); + LOAD_FUNCPTR(glXQueryVersion); + LOAD_FUNCPTR(glXUseXFont); + + /* GLX 1.1 */ + LOAD_FUNCPTR(glXGetClientString); + LOAD_FUNCPTR(glXQueryExtensionsString); + LOAD_FUNCPTR(glXQueryServerString); + + /* GLX 1.3 */ + LOAD_FUNCPTR(glXCreatePbuffer); + LOAD_FUNCPTR(glXCreateNewContext); + LOAD_FUNCPTR(glXDestroyPbuffer); + LOAD_FUNCPTR(glXMakeContextCurrent); + LOAD_FUNCPTR(glXGetCurrentReadDrawable); + LOAD_FUNCPTR(glXGetFBConfigs); + + /* Standard OpenGL calls */ + LOAD_FUNCPTR(glBindTexture); + LOAD_FUNCPTR(glBitmap); + LOAD_FUNCPTR(glCopyTexSubImage1D); + LOAD_FUNCPTR(glCopyTexImage2D); + LOAD_FUNCPTR(glCopyTexSubImage2D); + LOAD_FUNCPTR(glDrawBuffer); + LOAD_FUNCPTR(glEndList); + LOAD_FUNCPTR(glGetError); + LOAD_FUNCPTR(glGetIntegerv); + LOAD_FUNCPTR(glGetString); + LOAD_FUNCPTR(glNewList); + LOAD_FUNCPTR(glPixelStorei); + LOAD_FUNCPTR(glReadPixels); + LOAD_FUNCPTR(glTexImage2D); + LOAD_FUNCPTR(glFinish); + LOAD_FUNCPTR(glFlush); #undef LOAD_FUNCPTR /* It doesn't matter if these fail. They'll only be used if the driver reports the associated extension is available (and if a driver reports the extension is available but fails to provide the functions, it's quite broken) */ -#define LOAD_FUNCPTR(f) p##f = (void*)pglXGetProcAddressARB((const unsigned char*)#f); -/* NV GLX Extension */ -LOAD_FUNCPTR(glXAllocateMemoryNV) -LOAD_FUNCPTR(glXFreeMemoryNV) +#define LOAD_FUNCPTR(f) p##f = (void*)pglXGetProcAddressARB((const unsigned char*)#f) + /* NV GLX Extension */ + LOAD_FUNCPTR(glXAllocateMemoryNV); + LOAD_FUNCPTR(glXFreeMemoryNV); #undef LOAD_FUNCPTR - if(!X11DRV_WineGL_InitOpenglInfo()) { - wine_dlclose(opengl_handle, NULL, 0); - opengl_handle = NULL; - return FALSE; - } + if(!X11DRV_WineGL_InitOpenglInfo()) goto failed; wine_tsx11_lock(); - if (pglXQueryExtension(gdi_display, &error_base, &event_base) == True) { + if (pglXQueryExtension(gdi_display, &error_base, &event_base)) { TRACE("GLX is up and running error_base = %d\n", error_base); } else { - wine_dlclose(opengl_handle, NULL, 0); - opengl_handle = NULL; + wine_tsx11_unlock(); + ERR( "GLX extension is missing, disabling OpenGL.\n" ); + goto failed; } /* In case of GLX you have direct and indirect rendering. Most of the time direct rendering is used @@ -514,9 +522,9 @@ LOAD_FUNCPTR(glXFreeMemoryNV) X11DRV_WineGL_LoadExtensions(); wine_tsx11_unlock(); - return (opengl_handle != NULL); + return TRUE; -sym_not_found: +failed: wine_dlclose(opengl_handle, NULL, 0); opengl_handle = NULL; return FALSE; @@ -1050,10 +1058,7 @@ int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev, int bestStencil = -1; int bestAux = -1; - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return 0; - } + if (!has_opengl()) return 0; if (TRACE_ON(wgl)) { TRACE("(%p,%p)\n", physDev, ppfd); @@ -1289,11 +1294,8 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, int ret = 0; int fmt_count = 0; - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return 0; - } - + if (!has_opengl()) return 0; + TRACE("(%p,%d,%d,%p)\n", physDev, iPixelFormat, nBytes, ppfd); /* Look for the iPixelFormat in our list of supported formats. If it is supported we get the index in the FBConfig table and the number of supported formats back */ @@ -1536,10 +1538,7 @@ BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev, const PIXELFORMATDESCRIPTOR *ppfd) { TRACE("(%p,%d,%p)\n", physDev, iPixelFormat, ppfd); - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return FALSE; - } + if (!has_opengl()) return FALSE; if(physDev->current_pf) /* cannot change it if already set */ return (physDev->current_pf == iPixelFormat); @@ -1623,10 +1622,7 @@ HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) TRACE("(%p)->(PF:%d)\n", hdc, hdcPF); - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return 0; - } + if (!has_opengl()) return 0; fmt = ConvertPixelFormatWGLtoGLX(gdi_display, hdcPF, TRUE /* Offscreen */, &fmt_count); /* We can render using the iPixelFormat (1) of Wine's Main visual AND using some offscreen formats. @@ -1665,10 +1661,7 @@ BOOL X11DRV_wglDeleteContext(HGLRC hglrc) TRACE("(%p)\n", hglrc); - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return 0; - } + if (!has_opengl()) return 0; wine_tsx11_lock(); /* A game (Half Life not to name it) deletes twice the same context, @@ -1719,10 +1712,7 @@ PROC X11DRV_wglGetProcAddress(LPCSTR lpszProc) if (padding < 0) padding = 0; - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return 0; - } + if (!has_opengl()) return NULL; /* Check the table of WGL extensions to see if we need to return a WGL extension * or a function pointer to a native OpenGL function. */ @@ -1758,10 +1748,7 @@ BOOL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) { TRACE("(%p,%p)\n", hdc, hglrc); - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return FALSE; - } + if (!has_opengl()) return FALSE; wine_tsx11_lock(); if (hglrc == NULL) { @@ -1827,10 +1814,7 @@ BOOL X11DRV_wglMakeContextCurrentARB(X11DRV_PDEVICE* pDrawDev, X11DRV_PDEVICE* p TRACE("(%p,%p,%p)\n", pDrawDev, pReadDev, hglrc); - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return 0; - } + if (!has_opengl()) return 0; wine_tsx11_lock(); if (hglrc == NULL) { @@ -1874,10 +1858,7 @@ BOOL X11DRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) { TRACE("(%p, %p)\n", org, dest); - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return 0; - } + if (!has_opengl()) return FALSE; if (NULL != dest && dest->ctx != NULL) { ERR("Could not share display lists, context already created !\n"); @@ -2031,10 +2012,7 @@ BOOL X11DRV_wglUseFontBitmapsA(X11DRV_PDEVICE *physDev, DWORD first, DWORD count TRACE("(%p, %d, %d, %d) using font %ld\n", physDev->hdc, first, count, listBase, fid); - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return 0; - } + if (!has_opengl()) return FALSE; if (fid == 0) { return internal_wglUseFontBitmaps(physDev->hdc, first, count, listBase, GetGlyphOutlineA); @@ -2058,10 +2036,7 @@ BOOL X11DRV_wglUseFontBitmapsW(X11DRV_PDEVICE *physDev, DWORD first, DWORD count TRACE("(%p, %d, %d, %d) using font %ld\n", physDev->hdc, first, count, listBase, fid); - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return 0; - } + if (!has_opengl()) return FALSE; if (fid == 0) { return internal_wglUseFontBitmaps(physDev->hdc, first, count, listBase, GetGlyphOutlineW); @@ -3206,10 +3181,7 @@ BOOL X11DRV_wglSetPixelFormatWINE(X11DRV_PDEVICE *physDev, int iPixelFormat, con { TRACE("(%p,%d,%p)\n", physDev, iPixelFormat, ppfd); - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return FALSE; - } + if (!has_opengl()) return FALSE; if (physDev->current_pf == iPixelFormat) return TRUE; @@ -3482,11 +3454,8 @@ BOOL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev) GLXDrawable drawable; Wine_GLContext *ctx = NtCurrentTeb()->glContext; - if (!has_opengl()) { - ERR("No libGL on this box - disabling OpenGL support !\n"); - return 0; - } - + if (!has_opengl()) return FALSE; + TRACE("(%p)\n", physDev); drawable = get_glxdrawable(physDev); @@ -3549,6 +3518,12 @@ XVisualInfo *visual_from_fbconfig_id( XID fbconfig_id ) #else /* no OpenGL includes */ +static inline void opengl_error(void) +{ + static int warned; + if (!warned++) ERR("No OpenGL support compiled in.\n"); +} + int pixelformat_from_fbconfig_id(XID fbconfig_id) { return 0; @@ -3572,8 +3547,7 @@ Drawable create_glxpixmap(Display *display, XVisualInfo *vis, Pixmap parent) */ int X11DRV_ChoosePixelFormat(X11DRV_PDEVICE *physDev, const PIXELFORMATDESCRIPTOR *ppfd) { - ERR("No OpenGL support compiled in.\n"); - + opengl_error(); return 0; } @@ -3584,8 +3558,7 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, int iPixelFormat, UINT nBytes, PIXELFORMATDESCRIPTOR *ppfd) { - ERR("No OpenGL support compiled in.\n"); - + opengl_error(); return 0; } @@ -3593,8 +3566,7 @@ int X11DRV_DescribePixelFormat(X11DRV_PDEVICE *physDev, * GetPixelFormat (X11DRV.@) */ int X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) { - ERR("No OpenGL support compiled in.\n"); - + opengl_error(); return 0; } @@ -3604,8 +3576,7 @@ int X11DRV_GetPixelFormat(X11DRV_PDEVICE *physDev) { BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev, int iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd) { - ERR("No OpenGL support compiled in.\n"); - + opengl_error(); return FALSE; } @@ -3613,8 +3584,7 @@ BOOL X11DRV_SetPixelFormat(X11DRV_PDEVICE *physDev, * SwapBuffers (X11DRV.@) */ BOOL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev) { - ERR("No OpenGL support compiled in.\n"); - + opengl_error(); return FALSE; } @@ -3624,7 +3594,7 @@ BOOL X11DRV_SwapBuffers(X11DRV_PDEVICE *physDev) { * For OpenGL32 wglCopyContext. */ BOOL X11DRV_wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask) { - ERR("No OpenGL support compiled in.\n"); + opengl_error(); return FALSE; } @@ -3634,7 +3604,7 @@ BOOL X11DRV_wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask) { * For OpenGL32 wglCreateContext. */ HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) { - ERR("No OpenGL support compiled in.\n"); + opengl_error(); return NULL; } @@ -3644,7 +3614,7 @@ HGLRC X11DRV_wglCreateContext(X11DRV_PDEVICE *physDev) { * For OpenGL32 wglDeleteContext. */ BOOL X11DRV_wglDeleteContext(HGLRC hglrc) { - ERR("No OpenGL support compiled in.\n"); + opengl_error(); return FALSE; } @@ -3654,18 +3624,18 @@ BOOL X11DRV_wglDeleteContext(HGLRC hglrc) { * For OpenGL32 wglGetProcAddress. */ PROC X11DRV_wglGetProcAddress(LPCSTR lpszProc) { - ERR("No OpenGL support compiled in.\n"); + opengl_error(); return NULL; } HDC X11DRV_wglGetPbufferDCARB(X11DRV_PDEVICE *hDevice, void *hPbuffer) { - ERR("No OpenGL support compiled in.\n"); + opengl_error(); return NULL; } BOOL X11DRV_wglMakeContextCurrentARB(X11DRV_PDEVICE* hDrawDev, X11DRV_PDEVICE* hReadDev, HGLRC hglrc) { - ERR("No OpenGL support compiled in.\n"); + opengl_error(); return FALSE; } @@ -3675,7 +3645,7 @@ BOOL X11DRV_wglMakeContextCurrentARB(X11DRV_PDEVICE* hDrawDev, X11DRV_PDEVICE* h * For OpenGL32 wglMakeCurrent. */ BOOL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) { - ERR("No OpenGL support compiled in.\n"); + opengl_error(); return FALSE; } @@ -3685,7 +3655,7 @@ BOOL X11DRV_wglMakeCurrent(X11DRV_PDEVICE *physDev, HGLRC hglrc) { * For OpenGL32 wglShaderLists. */ BOOL X11DRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) { - ERR("No OpenGL support compiled in.\n"); + opengl_error(); return FALSE; } @@ -3696,7 +3666,7 @@ BOOL X11DRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2) { */ BOOL X11DRV_wglUseFontBitmapsA(X11DRV_PDEVICE *physDev, DWORD first, DWORD count, DWORD listBase) { - ERR("No OpenGL support compiled in.\n"); + opengl_error(); return FALSE; } @@ -3707,7 +3677,7 @@ BOOL X11DRV_wglUseFontBitmapsA(X11DRV_PDEVICE *physDev, DWORD first, DWORD count */ BOOL X11DRV_wglUseFontBitmapsW(X11DRV_PDEVICE *physDev, DWORD first, DWORD count, DWORD listBase) { - ERR("No OpenGL support compiled in.\n"); + opengl_error(); return FALSE; } @@ -3719,7 +3689,7 @@ BOOL X11DRV_wglUseFontBitmapsW(X11DRV_PDEVICE *physDev, DWORD first, DWORD count */ BOOL X11DRV_wglSetPixelFormatWINE(X11DRV_PDEVICE *physDev, int iPixelFormat, const PIXELFORMATDESCRIPTOR *ppfd) { - ERR("No OpenGL support compiled in.\n"); + opengl_error(); return FALSE; } diff --git a/dlls/winex11.drv/systray.c b/dlls/winex11.drv/systray.c index dffacf56012..17d3b07de42 100644 --- a/dlls/winex11.drv/systray.c +++ b/dlls/winex11.drv/systray.c @@ -230,9 +230,8 @@ static Window get_systray_selection_owner( Display *display ) /* dock the given X window with the NETWM system tray */ -static void dock_systray_window( HWND hwnd, Window systray_window ) +static void dock_systray_window( Display *display, HWND hwnd, Window systray_window ) { - Display *display = thread_display(); struct x11drv_win_data *data; XEvent ev; XSetWindowAttributes attr; @@ -284,6 +283,7 @@ static BOOL show_icon( struct tray_icon *icon ) RECT rect; static BOOL class_registered; Window systray_window; + Display *display = thread_display(); TRACE( "id=0x%x, hwnd=%p\n", icon->id, icon->owner ); @@ -308,7 +308,7 @@ static BOOL show_icon( struct tray_icon *icon ) class_registered = TRUE; } - if (!(systray_window = get_systray_selection_owner( thread_display() ))) return FALSE; + if (!(systray_window = get_systray_selection_owner( display ))) return FALSE; rect.left = 0; rect.top = 0; @@ -320,7 +320,7 @@ static BOOL show_icon( struct tray_icon *icon ) rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, NULL, icon ); create_tooltip( icon ); - dock_systray_window( icon->window, systray_window ); + dock_systray_window( display, icon->window, systray_window ); SetTimer( icon->window, 1, 1000, NULL ); ShowWindow( icon->window, SW_SHOWNA ); return TRUE; @@ -423,7 +423,7 @@ int wine_notify_icon( DWORD msg, NOTIFYICONDATAW *data ) switch (msg) { case NIM_ADD: - if (!get_systray_selection_owner( thread_display() )) + if (!get_systray_selection_owner( thread_init_display() )) return -1; /* fall back to default handling */ ret = add_icon( data ); break; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index dc0d64aa55e..e9f72834aa9 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1447,11 +1447,13 @@ static void destroy_whole_window( Display *display, struct x11drv_win_data *data */ void X11DRV_SetWindowText( HWND hwnd, LPCWSTR text ) { - Display *display = thread_display(); Window win; - if ((win = X11DRV_get_whole_window( hwnd )) && win != DefaultRootWindow(display)) + if ((win = X11DRV_get_whole_window( hwnd )) && win != DefaultRootWindow(gdi_display)) + { + Display *display = thread_init_display(); sync_window_text( display, win, text ); + } } @@ -1462,7 +1464,6 @@ void X11DRV_SetWindowText( HWND hwnd, LPCWSTR text ) */ void X11DRV_SetWindowStyle( HWND hwnd, DWORD old_style ) { - Display *display = thread_display(); struct x11drv_win_data *data; DWORD new_style, changed; @@ -1478,6 +1479,7 @@ void X11DRV_SetWindowStyle( HWND hwnd, DWORD old_style ) if (data->whole_window && is_window_rect_mapped( &data->window_rect )) { + Display *display = thread_display(); set_wm_hints( display, data ); if (!data->mapped) map_window( display, data, new_style ); } @@ -1490,7 +1492,7 @@ void X11DRV_SetWindowStyle( HWND hwnd, DWORD old_style ) { wine_tsx11_lock(); data->wm_hints->input = !(new_style & WS_DISABLED); - XSetWMHints( display, data->whole_window, data->wm_hints ); + XSetWMHints( thread_display(), data->whole_window, data->wm_hints ); wine_tsx11_unlock(); } } @@ -1503,7 +1505,6 @@ void X11DRV_SetWindowStyle( HWND hwnd, DWORD old_style ) void X11DRV_DestroyWindow( HWND hwnd ) { struct x11drv_thread_data *thread_data = x11drv_thread_data(); - Display *display = thread_data->display; struct x11drv_win_data *data; if (!(data = X11DRV_get_win_data( hwnd ))) return; @@ -1522,13 +1523,13 @@ void X11DRV_DestroyWindow( HWND hwnd ) wine_tsx11_unlock(); } - destroy_whole_window( display, data, FALSE ); - destroy_icon_window( display, data ); + destroy_whole_window( thread_data->display, data, FALSE ); + destroy_icon_window( thread_data->display, data ); if (data->colormap) { wine_tsx11_lock(); - XFreeColormap( display, data->colormap ); + XFreeColormap( thread_data->display, data->colormap ); wine_tsx11_unlock(); } @@ -1536,7 +1537,7 @@ void X11DRV_DestroyWindow( HWND hwnd ) if (data->hWMIconBitmap) DeleteObject( data->hWMIconBitmap ); if (data->hWMIconMask) DeleteObject( data->hWMIconMask); wine_tsx11_lock(); - XDeleteContext( display, (XID)hwnd, win_data_context ); + XDeleteContext( thread_data->display, (XID)hwnd, win_data_context ); wine_tsx11_unlock(); HeapFree( GetProcessHeap(), 0, data ); } @@ -1636,10 +1637,10 @@ BOOL X11DRV_CreateDesktopWindow( HWND hwnd ) */ BOOL X11DRV_CreateWindow( HWND hwnd ) { - Display *display = thread_display(); - - if (hwnd == GetDesktopWindow() && root_window != DefaultRootWindow( display )) + if (hwnd == GetDesktopWindow() && root_window != DefaultRootWindow( gdi_display )) { + Display *display = thread_init_display(); + /* the desktop win data can't be created lazily */ if (!create_desktop_win_data( display, hwnd )) return FALSE; } @@ -1654,9 +1655,12 @@ BOOL X11DRV_CreateWindow( HWND hwnd ) */ struct x11drv_win_data *X11DRV_get_win_data( HWND hwnd ) { + struct x11drv_thread_data *thread_data = x11drv_thread_data(); char *data; - if (!hwnd || XFindContext( thread_display(), (XID)hwnd, win_data_context, &data )) data = NULL; + if (!thread_data) return NULL; + if (!hwnd) return NULL; + if (XFindContext( thread_data->display, (XID)hwnd, win_data_context, &data )) data = NULL; return (struct x11drv_win_data *)data; } @@ -1668,11 +1672,16 @@ struct x11drv_win_data *X11DRV_get_win_data( HWND hwnd ) */ struct x11drv_win_data *X11DRV_create_win_data( HWND hwnd ) { - Display *display = thread_display(); + Display *display; struct x11drv_win_data *data; HWND parent; if (!(parent = GetAncestor( hwnd, GA_PARENT ))) return NULL; /* desktop */ + + /* don't create win data for HWND_MESSAGE windows */ + if (parent != GetDesktopWindow() && !GetAncestor( parent, GA_PARENT )) return NULL; + + display = thread_init_display(); if (!(data = alloc_win_data( display, hwnd ))) return NULL; GetWindowRect( hwnd, &data->window_rect ); @@ -1829,6 +1838,7 @@ void X11DRV_SetCapture( HWND hwnd, UINT flags ) { struct x11drv_thread_data *thread_data = x11drv_thread_data(); + if (!thread_data) return; if (!(flags & (GUI_INMOVESIZE | GUI_INMENUMODE))) return; if (hwnd) @@ -1892,7 +1902,6 @@ void X11DRV_SetParent( HWND hwnd, HWND parent, HWND old_parent ) * SetFocus (X11DRV.@) * * Set the X focus. - * Explicit colormap management seems to work only with OLVWM. */ void X11DRV_SetFocus( HWND hwnd ) { @@ -1900,18 +1909,7 @@ void X11DRV_SetFocus( HWND hwnd ) struct x11drv_win_data *data; XWindowChanges changes; - /* If setting the focus to 0, uninstall the colormap */ - if (!hwnd && root_window == DefaultRootWindow(display)) - { - wine_tsx11_lock(); - if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE) - XUninstallColormap( display, X11DRV_PALETTE_PaletteXColormap ); - wine_tsx11_unlock(); - return; - } - - hwnd = GetAncestor( hwnd, GA_ROOT ); - + if (!(hwnd = GetAncestor( hwnd, GA_ROOT ))) return; if (!(data = X11DRV_get_win_data( hwnd ))) return; if (data->managed || !data->whole_window) return; @@ -1926,8 +1924,6 @@ void X11DRV_SetFocus( HWND hwnd ) XSetInputFocus( display, data->whole_window, RevertToParent, /* CurrentTime */ GetMessageTime() - EVENT_x11_time_to_win32_time(0)); - if (X11DRV_PALETTE_PaletteFlags & X11DRV_PALETTE_PRIVATE) - XInstallColormap( display, X11DRV_PALETTE_PaletteXColormap ); } wine_tsx11_unlock(); } @@ -1940,8 +1936,8 @@ void X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, UINT swp_flags, const RECT *rectWindow, const RECT *rectClient, const RECT *visible_rect, const RECT *valid_rects ) { - struct x11drv_thread_data *thread_data = x11drv_thread_data(); - Display *display = thread_data->display; + struct x11drv_thread_data *thread_data; + Display *display; struct x11drv_win_data *data = X11DRV_get_win_data( hwnd ); DWORD new_style = GetWindowLongW( hwnd, GWL_STYLE ); RECT old_whole_rect, old_client_rect; @@ -1954,6 +1950,9 @@ void X11DRV_SetWindowPos( HWND hwnd, HWND insert_after, UINT swp_flags, if (!(data = X11DRV_create_win_data( hwnd ))) return; } + thread_data = x11drv_thread_data(); + display = thread_data->display; + /* check if we need to switch the window to managed */ if (!data->managed && data->whole_window && is_window_managed( hwnd, swp_flags, rectWindow )) { diff --git a/dlls/winex11.drv/wintab.c b/dlls/winex11.drv/wintab.c index ed04ad56a5d..e73f000d9a9 100644 --- a/dlls/winex11.drv/wintab.c +++ b/dlls/winex11.drv/wintab.c @@ -490,7 +490,7 @@ void X11DRV_LoadTabletInfo(HWND hwnddefault) const WCHAR SZ_DEVICE_NAME[] = {'W','i','n','e',' ','T','a','b','l','e','t',' ','D','e','v','i','c','e',0}; const WCHAR SZ_NON_PLUGINPLAY[] = {'n','o','n','-','p','l','u','g','i','n','p','l','a','y',0}; - struct x11drv_thread_data *data = x11drv_thread_data(); + struct x11drv_thread_data *data = x11drv_init_thread_data(); int num_devices; int loop; XDeviceInfo *devices; @@ -961,7 +961,7 @@ static void proximity_event( HWND hwnd, XEvent *event ) */ int X11DRV_AttachEventQueueToTablet(HWND hOwner) { - struct x11drv_thread_data *data = x11drv_thread_data(); + struct x11drv_thread_data *data = x11drv_init_thread_data(); int num_devices; int loop; int cur_loop; diff --git a/dlls/winex11.drv/x11ddraw.c b/dlls/winex11.drv/x11ddraw.c index e0bda0a11fa..492d6783445 100644 --- a/dlls/winex11.drv/x11ddraw.c +++ b/dlls/winex11.drv/x11ddraw.c @@ -77,6 +77,8 @@ static LRESULT WINAPI GrabWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM TRACE("hwnd=%p, grab=%ld\n", hWnd, wParam); + if (!data) return 0; + if (wParam) { /* find the X11 window that ddraw uses */ @@ -106,11 +108,12 @@ static LRESULT WINAPI GrabWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM static void GrabPointer(BOOL grab) { if(grab) { + Display *display = thread_display(); Window window = X11DRV_get_whole_window(GetFocus()); - if(window) + if(window && display) { wine_tsx11_lock(); - XSetInputFocus(thread_display(), window, RevertToParent, CurrentTime); + XSetInputFocus(display, window, RevertToParent, CurrentTime); wine_tsx11_unlock(); } } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index a1d765b73ff..6d8ad899e05 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -522,12 +522,22 @@ extern DWORD thread_data_tls_index; static inline struct x11drv_thread_data *x11drv_thread_data(void) { - struct x11drv_thread_data *data = TlsGetValue( thread_data_tls_index ); - if (!data) data = x11drv_init_thread_data(); - return data; + return TlsGetValue( thread_data_tls_index ); } -static inline Display *thread_display(void) { return x11drv_thread_data()->display; } +/* retrieve the thread display, or NULL if not created yet */ +static inline Display *thread_display(void) +{ + struct x11drv_thread_data *data = x11drv_thread_data(); + if (!data) return NULL; + return data->display; +} + +/* retrieve the thread display, creating it if needed */ +static inline Display *thread_init_display(void) +{ + return x11drv_init_thread_data()->display; +} static inline size_t get_property_size( int format, unsigned long count ) { diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 4ca1bb64d22..75b9bd9f23e 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -616,7 +616,9 @@ static void set_queue_display_fd( Display *display ) */ struct x11drv_thread_data *x11drv_init_thread_data(void) { - struct x11drv_thread_data *data; + struct x11drv_thread_data *data = x11drv_thread_data(); + + if (data) return data; if (!(data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data) ))) { diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index 85125836359..252dacddbb6 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -359,7 +359,7 @@ BOOL X11DRV_InitXIM( const char *input_style ) } -static void X11DRV_OpenIM(Display *display, XPointer p, XPointer data); +static void open_xim_callback( Display *display, XPointer ptr, XPointer data ); static void X11DRV_DestroyIM(XIM xim, XPointer p, XPointer data) { @@ -369,7 +369,7 @@ static void X11DRV_DestroyIM(XIM xim, XPointer p, XPointer data) thread_data->xim = NULL; ximStyle = 0; wine_tsx11_lock(); - XRegisterIMInstantiateCallback( thread_data->display, NULL, NULL, NULL, X11DRV_OpenIM, NULL ); + XRegisterIMInstantiateCallback( thread_data->display, NULL, NULL, NULL, open_xim_callback, NULL ); wine_tsx11_unlock(); } @@ -378,7 +378,7 @@ static void X11DRV_DestroyIM(XIM xim, XPointer p, XPointer data) * * Should always be called with the x11 lock held */ -static void X11DRV_OpenIM(Display *display, XPointer ptr, XPointer data) +static BOOL open_xim( Display *display ) { struct x11drv_thread_data *thread_data = x11drv_thread_data(); XIMStyle ximStyleCallback, ximStyleNone; @@ -391,7 +391,7 @@ static void X11DRV_OpenIM(Display *display, XPointer ptr, XPointer data) if (xim == NULL) { WARN("Could not open input method.\n"); - return; + return FALSE; } destroy.client_data = NULL; @@ -410,7 +410,7 @@ static void X11DRV_OpenIM(Display *display, XPointer ptr, XPointer data) { WARN("Could not find supported input style.\n"); XCloseIM(xim); - return; + return FALSE; } else { @@ -471,18 +471,26 @@ static void X11DRV_OpenIM(Display *display, XPointer ptr, XPointer data) } thread_data->xim = xim; - XUnregisterIMInstantiateCallback(display, NULL, NULL, NULL, X11DRV_OpenIM, NULL); wine_tsx11_unlock(); IME_UpdateAssociation(NULL); wine_tsx11_lock(); + return TRUE; } +static void open_xim_callback( Display *display, XPointer ptr, XPointer data ) +{ + if (open_xim( display )) + XUnregisterIMInstantiateCallback( display, NULL, NULL, NULL, open_xim_callback, NULL); +} void X11DRV_SetupXIM(void) { + Display *display = thread_display(); + wine_tsx11_lock(); - XRegisterIMInstantiateCallback(thread_display(), NULL, NULL, NULL, X11DRV_OpenIM, NULL); + if (!open_xim( display )) + XRegisterIMInstantiateCallback( display, NULL, NULL, NULL, open_xim_callback, NULL ); wine_tsx11_unlock(); } diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index 79e35111eaa..fdfd9da35d6 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -1329,6 +1329,8 @@ static BOOL HTTP_ResolveName(LPWININETHTTPREQW lpwhr) char szaddr[32]; LPWININETHTTPSESSIONW lpwhs = lpwhr->lpHttpSession; + if (lpwhs->socketAddress.sin_addr.s_addr) return TRUE; + INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_RESOLVING_NAME, lpwhs->lpszServerName, @@ -2016,16 +2018,6 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(LPWININETHTTPSESSIONW lpwhs, INTERNET_STATUS_HANDLE_CREATED, &handle, sizeof(handle)); - /* - * A STATUS_REQUEST_COMPLETE is NOT sent here as per my tests on windows - */ - - if (!HTTP_ResolveName(lpwhr)) - { - InternetCloseHandle( handle ); - handle = NULL; - } - lend: if( lpwhr ) WININET_Release( &lpwhr->hdr ); @@ -3168,9 +3160,6 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, assert(lpwhr->hdr.htype == WH_HHTTPREQ); - /* Clear any error information */ - INTERNET_SetLastError(0); - /* if the verb is NULL default to GET */ if (!lpwhr->lpszVerb) lpwhr->lpszVerb = WININET_strdupW(szGET); @@ -3193,6 +3182,11 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders, HTTP_HttpAddRequestHeadersW(lpwhr, agent_header, strlenW(agent_header), HTTP_ADDREQ_FLAG_ADD_IF_NEW); HeapFree(GetProcessHeap(), 0, agent_header); } + if (lpwhr->hdr.dwFlags & INTERNET_FLAG_PRAGMA_NOCACHE) + { + static const WCHAR pragma_nocache[] = {'P','r','a','g','m','a',':',' ','n','o','-','c','a','c','h','e','\r','\n',0}; + HTTP_HttpAddRequestHeadersW(lpwhr, pragma_nocache, strlenW(pragma_nocache), HTTP_ADDREQ_FLAG_ADD_IF_NEW); + } do { @@ -3412,6 +3406,7 @@ lend: sizeof(INTERNET_ASYNC_RESULT)); TRACE("<--\n"); + if (bSuccess) INTERNET_SetLastError(ERROR_SUCCESS); return bSuccess; } @@ -3597,6 +3592,7 @@ static BOOL HTTP_OpenConnection(LPWININETHTTPREQW lpwhr) bSuccess = TRUE; goto lend; } + if (!HTTP_ResolveName(lpwhr)) goto lend; lpwhs = lpwhr->lpHttpSession; @@ -4141,6 +4137,9 @@ static BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, DWORD index) return FALSE; lpwhr->nCustHeaders--; + HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[index].lpszField); + HeapFree(GetProcessHeap(), 0, lpwhr->pCustHeaders[index].lpszValue); + memmove( &lpwhr->pCustHeaders[index], &lpwhr->pCustHeaders[index+1], (lpwhr->nCustHeaders - index)* sizeof(HTTPHEADERW) ); memset( &lpwhr->pCustHeaders[lpwhr->nCustHeaders], 0, sizeof(HTTPHEADERW) ); diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index 1ae8ccef898..388a2a9c398 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -1490,6 +1490,8 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR } else { + if (lpUC->lpszUrlPath && (lpUC->dwUrlPathLength > 0)) + lpUC->lpszUrlPath[0] = 0; lpUC->dwUrlPathLength = 0; } @@ -2258,44 +2260,44 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption, break; case INTERNET_OPTION_ERROR_MASK: { - unsigned long flags=*(unsigned long*)lpBuffer; - FIXME("Option INTERNET_OPTION_ERROR_MASK(%ld): STUB\n",flags); + ULONG flags = *(ULONG *)lpBuffer; + FIXME("Option INTERNET_OPTION_ERROR_MASK(%d): STUB\n", flags); } break; case INTERNET_OPTION_CODEPAGE: { - unsigned long codepage=*(unsigned long*)lpBuffer; - FIXME("Option INTERNET_OPTION_CODEPAGE (%ld): STUB\n",codepage); + ULONG codepage = *(ULONG *)lpBuffer; + FIXME("Option INTERNET_OPTION_CODEPAGE (%d): STUB\n", codepage); } break; case INTERNET_OPTION_REQUEST_PRIORITY: { - unsigned long priority=*(unsigned long*)lpBuffer; - FIXME("Option INTERNET_OPTION_REQUEST_PRIORITY (%ld): STUB\n",priority); + ULONG priority = *(ULONG *)lpBuffer; + FIXME("Option INTERNET_OPTION_REQUEST_PRIORITY (%d): STUB\n", priority); } break; case INTERNET_OPTION_CONNECT_TIMEOUT: { - unsigned long connecttimeout=*(unsigned long*)lpBuffer; - FIXME("Option INTERNET_OPTION_CONNECT_TIMEOUT (%ld): STUB\n",connecttimeout); + ULONG connecttimeout = *(ULONG *)lpBuffer; + FIXME("Option INTERNET_OPTION_CONNECT_TIMEOUT (%d): STUB\n", connecttimeout); } break; case INTERNET_OPTION_DATA_RECEIVE_TIMEOUT: { - unsigned long receivetimeout=*(unsigned long*)lpBuffer; - FIXME("Option INTERNET_OPTION_DATA_RECEIVE_TIMEOUT (%ld): STUB\n",receivetimeout); + ULONG receivetimeout = *(ULONG *)lpBuffer; + FIXME("Option INTERNET_OPTION_DATA_RECEIVE_TIMEOUT (%d): STUB\n", receivetimeout); } break; case INTERNET_OPTION_MAX_CONNS_PER_SERVER: { - unsigned long conns=*(unsigned long*)lpBuffer; - FIXME("Option INTERNET_OPTION_MAX_CONNS_PER_SERVER (%ld): STUB\n",conns); + ULONG conns = *(ULONG *)lpBuffer; + FIXME("Option INTERNET_OPTION_MAX_CONNS_PER_SERVER (%d): STUB\n", conns); } break; case INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER: { - unsigned long conns=*(unsigned long*)lpBuffer; - FIXME("Option INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER (%ld): STUB\n",conns); + ULONG conns = *(ULONG *)lpBuffer; + FIXME("Option INTERNET_OPTION_MAX_CONNS_PER_1_0_SERVER (%d): STUB\n", conns); } break; case INTERNET_OPTION_RESET_URLCACHE_SESSION: @@ -2312,11 +2314,17 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption, break; case INTERNET_OPTION_SEND_TIMEOUT: case INTERNET_OPTION_RECEIVE_TIMEOUT: - FIXME("INTERNET_OPTION_SEND/RECEIVE_TIMEOUT\n"); + { + ULONG timeout = *(ULONG *)lpBuffer; + FIXME("INTERNET_OPTION_SEND/RECEIVE_TIMEOUT %d\n", timeout); break; + } case INTERNET_OPTION_CONNECT_RETRIES: - FIXME("Option INTERNET_OPTION_CONNECT_RETRIES: STUB\n"); + { + ULONG retries = *(ULONG *)lpBuffer; + FIXME("INTERNET_OPTION_CONNECT_RETRIES %d\n", retries); break; + } case INTERNET_OPTION_CONTEXT_VALUE: FIXME("Option INTERNET_OPTION_CONTEXT_VALUE; STUB\n"); break; diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c index 9ad9790e875..513afb88138 100644 --- a/dlls/wininet/tests/http.c +++ b/dlls/wininet/tests/http.c @@ -270,8 +270,6 @@ static void InternetReadFile_test(int flags) CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED); SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED); - SET_WINE_ALLOW(INTERNET_STATUS_RESOLVING_NAME); - SET_WINE_ALLOW(INTERNET_STATUS_NAME_RESOLVED); trace("HttpOpenRequestA <--\n"); hor = HttpOpenRequestA(hic, "GET", "/about/", NULL, NULL, types, @@ -297,11 +295,8 @@ static void InternetReadFile_test(int flags) ok(!strcmp(buffer, "http://www.winehq.org/about/"), "Wrong URL %s\n", buffer); CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED); - todo_wine - { - CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME); - CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED); - } + CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME); + CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED); if (first_connection_to_test_url) { SET_EXPECT(INTERNET_STATUS_RESOLVING_NAME); @@ -516,8 +511,6 @@ static void InternetReadFileExA_test(int flags) CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED); SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED); - SET_WINE_ALLOW(INTERNET_STATUS_RESOLVING_NAME); - SET_WINE_ALLOW(INTERNET_STATUS_NAME_RESOLVED); trace("HttpOpenRequestA <--\n"); hor = HttpOpenRequestA(hic, "GET", "/about/", NULL, NULL, types, @@ -538,11 +531,8 @@ static void InternetReadFileExA_test(int flags) if (hor == 0x0) goto abort; CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED); - todo_wine - { - CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME); - CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED); - } + CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME); + CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED); if (first_connection_to_test_url) { SET_EXPECT(INTERNET_STATUS_RESOLVING_NAME); @@ -1687,7 +1677,7 @@ static void test_header_handling_order(int port) size = sizeof(status); ret = HttpQueryInfo( request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL ); ok(ret, "HttpQueryInfo failed\n"); - ok(status == 200, "request failed with status %u\n", status); + ok(status == 200 || status == 400 /* IE6 */, "request failed with status %u\n", status); InternetCloseHandle(request); InternetCloseHandle(connect); diff --git a/dlls/wininet/tests/url.c b/dlls/wininet/tests/url.c index ccc56076bad..e9f2439e781 100644 --- a/dlls/wininet/tests/url.c +++ b/dlls/wininet/tests/url.c @@ -268,6 +268,7 @@ static void InternetCrackUrlW_test(void) '=','I','D','E','&','A','C','T','I','O','N','=','I','D','E','_','D','E','F','A', 'U','L','T', 0 }; static const WCHAR url2[] = { '.','.','/','R','i','t','z','.','x','m','l',0 }; + static const WCHAR url3[] = { 'h','t','t','p',':','/','/','x','.','o','r','g',0 }; URL_COMPONENTSW comp; WCHAR scheme[20], host[20], user[20], pwd[20], urlpart[50], extra[50]; DWORD error; @@ -389,6 +390,32 @@ static void InternetCrackUrlW_test(void) "InternetCrackUrl should have failed with error ERROR_INTERNET_UNRECOGNIZED_SCHEME instead of error %d\n", GetLastError()); } + + /* Test to see whether cracking a URL without a filename initializes urlpart */ + urlpart[0]=0xba; + scheme[0]=0; + extra[0]=0; + host[0]=0; + user[0]=0; + pwd[0]=0; + memset(&comp, 0, sizeof comp); + comp.dwStructSize = sizeof comp; + comp.lpszScheme = scheme; + comp.dwSchemeLength = sizeof scheme; + comp.lpszHostName = host; + comp.dwHostNameLength = sizeof host; + comp.lpszUserName = user; + comp.dwUserNameLength = sizeof user; + comp.lpszPassword = pwd; + comp.dwPasswordLength = sizeof pwd; + comp.lpszUrlPath = urlpart; + comp.dwUrlPathLength = sizeof urlpart; + comp.lpszExtraInfo = extra; + comp.dwExtraInfoLength = sizeof extra; + r = InternetCrackUrlW(url3, 0, 0, &comp ); + ok( r, "InternetCrackUrlW failed unexpectedly\n"); + ok( host[0] == 'x', "host should be x.org\n"); + ok( urlpart[0] == 0, "urlpart should be empty\n"); } static void fill_url_components(LPURL_COMPONENTS lpUrlComponents) diff --git a/dlls/winmm/tests/mixer.c b/dlls/winmm/tests/mixer.c index ed68f89be71..4961547e26b 100644 --- a/dlls/winmm/tests/mixer.c +++ b/dlls/winmm/tests/mixer.c @@ -491,6 +491,8 @@ static void mixer_test_deviceA(int device) array=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, mixerlineA.cControls*sizeof(MIXERCONTROLA)); if (array) { + memset(&controls, 0, sizeof(controls)); + rc=mixerGetLineControlsA((HMIXEROBJ)mix,0, MIXER_GETLINECONTROLSF_ALL); ok(rc==MMSYSERR_INVALPARAM, diff --git a/dlls/winmm/tests/mmio.c b/dlls/winmm/tests/mmio.c index 5fac90a72d6..e9458917666 100644 --- a/dlls/winmm/tests/mmio.c +++ b/dlls/winmm/tests/mmio.c @@ -30,9 +30,15 @@ static DWORD RIFF_buf[] = { - FOURCC_RIFF, 7*sizeof(DWORD)+sizeof(MainAVIHeader), mmioFOURCC('A','V','I',' '), - FOURCC_LIST, sizeof(DWORD)+sizeof(MMCKINFO)+sizeof(MainAVIHeader), listtypeAVIHEADER, - ckidAVIMAINHDR, sizeof(MainAVIHeader), 0xdeadbeef, 0xdeadbeef, + FOURCC_RIFF, 32*sizeof(DWORD), mmioFOURCC('A','V','I',' '), + FOURCC_LIST, 29*sizeof(DWORD), listtypeAVIHEADER, ckidAVIMAINHDR, + sizeof(MainAVIHeader), 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, + 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,0xdeadbeef, + 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,0xdeadbeef, + 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, + FOURCC_LIST, 10*sizeof(DWORD),listtypeSTREAMHEADER, ckidSTREAMHEADER, + 7*sizeof(DWORD), streamtypeVIDEO, 0xdeadbeef, 0xdeadbeef, + 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -83,6 +89,25 @@ static void test_mmioDescend(char *fname) (LPCSTR)&ck.ckid, ck.cksize, (LPCSTR)&ck.fccType, ck.dwDataOffset, ck.dwFlags); + /* Skip chunk data */ + mmioSeek(hmmio, ck.cksize, SEEK_CUR); + + ret = mmioDescend(hmmio, &ckList, &ckList, 0); + ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); + ok(ckList.ckid == FOURCC_LIST, "wrong ckid: %04x\n", ckList.ckid); + ok(ckList.fccType == listtypeSTREAMHEADER, "wrong fccType: %04x\n", ckList.fccType); + trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n", + (LPCSTR)&ckList.ckid, ckList.cksize, (LPCSTR)&ckList.fccType, + ckList.dwDataOffset, ckList.dwFlags); + + ret = mmioDescend(hmmio, &ck, &ckList, 0); + ok(ret == MMSYSERR_NOERROR, "mmioDescend error %u\n", ret); + ok(ck.ckid == ckidSTREAMHEADER, "wrong ckid: %04x\n", ck.ckid); + ok(ck.fccType == 0, "wrong fccType: %04x\n", ck.fccType); + trace("ckid %4.4s cksize %04x fccType %4.4s off %04x flags %04x\n", + (LPCSTR)&ck.ckid, ck.cksize, (LPCSTR)&ck.fccType, + ck.dwDataOffset, ck.dwFlags); + /* test various mmioDescend flags */ mmioSeek(hmmio, 0, SEEK_SET); diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c index 5057c0da69f..b49dd531d06 100644 --- a/dlls/winspool.drv/info.c +++ b/dlls/winspool.drv/info.c @@ -524,6 +524,7 @@ static BOOL CUPS_LoadPrinters(void) TRACE("Printer already exists\n"); RegDeleteValueW(hkeyPrinter, May_Delete_Value); RegCloseKey(hkeyPrinter); + add_printer_driver(dests[i].name); } else { static CHAR data_type[] = "RAW", print_proc[] = "WinPrint", @@ -661,6 +662,7 @@ PRINTCAP_ParseEntry(const char *pent, BOOL isfirst) { TRACE("Printer already exists\n"); RegDeleteValueW(hkeyPrinter, May_Delete_Value); RegCloseKey(hkeyPrinter); + add_printer_driver(devname); } else { static CHAR data_type[] = "RAW", print_proc[] = "WinPrint", @@ -2295,10 +2297,10 @@ BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors) MONITOR_INFO_2W mi2w; mi2a = (LPMONITOR_INFO_2A) pMonitors; - TRACE("(%s, %d, %p) : %s %s %s\n", debugstr_a(pName), Level, pMonitors, - mi2a ? debugstr_a(mi2a->pName) : NULL, - mi2a ? debugstr_a(mi2a->pEnvironment) : NULL, - mi2a ? debugstr_a(mi2a->pDLLName) : NULL); + TRACE("(%s, %d, %p) : %s %s %s\n", debugstr_a(pName), Level, pMonitors, + debugstr_a(mi2a ? mi2a->pName : NULL), + debugstr_a(mi2a ? mi2a->pEnvironment : NULL), + debugstr_a(mi2a ? mi2a->pDLLName : NULL)); if (Level != 2) { SetLastError(ERROR_INVALID_LEVEL); @@ -2371,10 +2373,10 @@ BOOL WINAPI AddMonitorW(LPWSTR pName, DWORD Level, LPBYTE pMonitors) BOOL res = FALSE; mi2w = (LPMONITOR_INFO_2W) pMonitors; - TRACE("(%s, %d, %p) : %s %s %s\n", debugstr_w(pName), Level, pMonitors, - mi2w ? debugstr_w(mi2w->pName) : NULL, - mi2w ? debugstr_w(mi2w->pEnvironment) : NULL, - mi2w ? debugstr_w(mi2w->pDLLName) : NULL); + TRACE("(%s, %d, %p) : %s %s %s\n", debugstr_w(pName), Level, pMonitors, + debugstr_w(mi2w ? mi2w->pName : NULL), + debugstr_w(mi2w ? mi2w->pEnvironment : NULL), + debugstr_w(mi2w ? mi2w->pDLLName : NULL)); if (Level != 2) { SetLastError(ERROR_INVALID_LEVEL); @@ -2665,7 +2667,7 @@ BOOL WINAPI DeletePortW (LPWSTR pName, HWND hWnd, LPWSTR pPortName) else { FIXME("not implemented for %s (%p: %s => %p: %s)\n", debugstr_w(pPortName), - pm, pm ? debugstr_w(pm->dllname) : NULL, pui, pui ? debugstr_w(pui->dllname) : NULL); + pm, debugstr_w(pm ? pm->dllname : NULL), pui, debugstr_w(pui ? pui->dllname : NULL)); /* XP: ERROR_NOT_SUPPORTED, NT351,9x: ERROR_INVALID_PARAMETER */ SetLastError(ERROR_NOT_SUPPORTED); @@ -6551,7 +6553,7 @@ BOOL WINAPI AddPortW(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName) else { FIXME("not implemented for %s (%p: %s => %p: %s)\n", debugstr_w(pMonitorName), - pm, pm ? debugstr_w(pm->dllname) : NULL, pui, pui ? debugstr_w(pui->dllname) : NULL); + pm, debugstr_w(pm ? pm->dllname : NULL), pui, debugstr_w(pui ? pui->dllname : NULL)); /* XP: ERROR_NOT_SUPPORTED, NT351,9x: ERROR_INVALID_PARAMETER */ SetLastError(ERROR_NOT_SUPPORTED); @@ -6989,7 +6991,7 @@ BOOL WINAPI ConfigurePortW(LPWSTR pName, HWND hWnd, LPWSTR pPortName) else { FIXME("not implemented for %s (%p: %s => %p: %s)\n", debugstr_w(pPortName), - pm, pm ? debugstr_w(pm->dllname) : NULL, pui, pui ? debugstr_w(pui->dllname) : NULL); + pm, debugstr_w(pm ? pm->dllname : NULL), pui, debugstr_w(pui ? pui->dllname : NULL)); /* XP: ERROR_NOT_SUPPORTED, NT351,9x: ERROR_INVALID_PARAMETER */ SetLastError(ERROR_NOT_SUPPORTED); diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index e41a646593a..fa908b4b78c 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1103,7 +1103,17 @@ static int WS2_recv( int fd, struct iovec* iov, int count, if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 ) return -1; - if ( lpFrom && + /* if this socket is connected and lpFrom is not NULL, Linux doesn't give us + * msg_name and msg_namelen from recvmsg, but it does set msg_namelen to zero. + * + * quoting linux 2.6 net/ipv4/tcp.c: + * "According to UNIX98, msg_name/msg_namelen are ignored + * on connected socket. I was just happy when found this 8) --ANK" + * + * likewise MSDN says that lpFrom and lpFromlen are ignored for + * connection-oriented sockets, so don't try to update lpFrom. + */ + if ( lpFrom && hdr.msg_namelen && ws_sockaddr_u2ws( &unix_sockaddr.addr, lpFrom, lpFromlen ) != 0 ) { /* The from buffer was too small, but we read the data diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 8ee5c37d87e..1256c2dcb73 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -31,7 +31,7 @@ #include #define MAX_CLIENTS 4 /* Max number of clients */ -#define NUM_TESTS 3 /* Number of tests performed */ +#define NUM_TESTS 4 /* Number of tests performed */ #define FIRST_CHAR 'A' /* First character in transferred pattern */ #define BIND_SLEEP 10 /* seconds to wait between attempts to bind() */ #define BIND_TRIES 6 /* Number of bind() attempts */ @@ -269,6 +269,16 @@ static int do_synchronous_recv ( SOCKET s, char *buf, int buflen, int recvlen ) return p - buf; } +static int do_synchronous_recvfrom ( SOCKET s, char *buf, int buflen,int flags,struct sockaddr *from, socklen_t *fromlen, int recvlen ) +{ + char* last = buf + buflen, *p; + int n = 1; + for ( p = buf; n > 0 && p < last; p += n ) + n = recvfrom ( s, p, min ( recvlen, last - p ), 0, from, fromlen ); + wsa_ok ( n, 0 <=, "do_synchronous_recv (%x): error %d:\n" ); + return p - buf; +} + /* * Call this routine right after thread startup. * SO_OPENTYPE must by 0, regardless what the server did. @@ -627,6 +637,76 @@ static VOID WINAPI simple_client ( client_params *par ) } /* + * simple_mixed_client: mixing send and recvfrom + */ +static VOID WINAPI simple_mixed_client ( client_params *par ) +{ + test_params *gen = par->general; + client_memory *mem; + int n_sent, n_recvd, n_expected = gen->n_chunks * gen->chunk_size, id; + char *p; + socklen_t fromLen = sizeof(mem->addr); + struct sockaddr test; + + id = GetCurrentThreadId(); + trace ( "simple_client (%x): starting\n", id ); + /* wait here because we want to call set_so_opentype before creating a socket */ + WaitForSingleObject ( server_ready, INFINITE ); + trace ( "simple_client (%x): server ready\n", id ); + + check_so_opentype (); + set_so_opentype ( FALSE ); /* non-overlapped */ + client_start ( par ); + mem = TlsGetValue ( tls ); + + /* Connect */ + wsa_ok ( connect ( mem->s, (struct sockaddr*) &mem->addr, sizeof ( mem->addr ) ), + 0 ==, "simple_client (%x): connect error: %d\n" ); + ok ( set_blocking ( mem->s, TRUE ) == 0, + "simple_client (%x): failed to set blocking mode\n", id ); + trace ( "simple_client (%x) connected\n", id ); + + /* send data to server */ + n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, par->buflen ); + ok ( n_sent == n_expected, + "simple_client (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected ); + + /* shutdown send direction */ + wsa_ok ( shutdown ( mem->s, SD_SEND ), 0 ==, "simple_client (%x): shutdown failed: %d\n" ); + + /* this shouldn't change, since lpFrom, is not updated on + connection oriented sockets - exposed by bug 11640 + */ + ((struct sockaddr_in*)&test)->sin_addr.s_addr = inet_addr("0.0.0.0"); + + /* Receive data echoed back & check it */ + n_recvd = do_synchronous_recvfrom ( mem->s, + mem->recv_buf, + n_expected, + 0, + (struct sockaddr *)&test, + &fromLen, + par->buflen ); + ok ( n_recvd == n_expected, + "simple_client (%x): received less data than expected: %d of %d\n", id, n_recvd, n_expected ); + + /* check that lpFrom was not updated */ + ok(0 == + strcmp( + inet_ntoa(((struct sockaddr_in*)&test)->sin_addr), + "0.0.0.0"), "lpFrom shouldn't be updated on connection oriented sockets\n"); + + /* check data */ + p = test_buffer ( mem->recv_buf, gen->chunk_size, gen->n_chunks ); + ok ( p == NULL, "simple_client (%x): test pattern error: %d\n", id, p - mem->recv_buf); + + /* cleanup */ + read_zero_bytes ( mem->s ); + trace ( "simple_client (%x) exiting\n", id ); + client_stop (); +} + +/* * event_client: An event-driven client */ static void WINAPI event_client ( client_params *par ) @@ -1013,6 +1093,27 @@ static test_setup tests [NUM_TESTS] = 0, 128 } + }, + /* Test 3: synchronous mixed client and server */ + { + { + STD_STREAM_SOCKET, + 2048, + 16, + 2 + }, + simple_server, + { + NULL, + 0, + 64 + }, + simple_mixed_client, + { + NULL, + 0, + 128 + } } }; @@ -1026,6 +1127,7 @@ static void test_UDP(void) char buf[16]; int ss, i, n_recv, n_sent; + memset (buf,0,sizeof(buf)); for ( i = NUM_UDP_PEERS - 1; i >= 0; i-- ) { ok ( ( peer[i].s = socket ( AF_INET, SOCK_DGRAM, 0 ) ) != INVALID_SOCKET, "UDP: socket failed\n" ); @@ -1920,7 +2022,7 @@ static void test_send(void) goto end; } - buffer = HeapAlloc(GetProcessHeap(), 0, buflen); + buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buflen); if (buffer == NULL) { ok(0, "HeapAlloc failed, error %d\n", GetLastError()); diff --git a/include/Makefile.in b/include/Makefile.in index c36897552d0..54747a6f9be 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -67,6 +67,9 @@ IDL_H_SRCS = \ unknwn.idl \ urlhist.idl \ urlmon.idl \ + vmr9.idl \ + wine/dcetypes.idl \ + wine/epm.idl \ wine/itss.idl \ wine/svcctl.idl \ wtypes.idl \ diff --git a/include/axcore.idl b/include/axcore.idl index bb9f5e701ed..52e695935be 100644 --- a/include/axcore.idl +++ b/include/axcore.idl @@ -48,7 +48,11 @@ cpp_quote("#define MAX_PIN_NAME 128") cpp_quote("#define MAX_FILTER_NAME 128") typedef LONGLONG REFERENCE_TIME; + +cpp_quote("#ifndef REFTIME_DEFINED") +cpp_quote("#define REFTIME_DEFINED") typedef DOUBLE REFTIME; +cpp_quote("#endif") typedef DWORD_PTR HSEMAPHORE; typedef DWORD_PTR HEVENT; diff --git a/include/config.h.in b/include/config.h.in index 9833b2387a8..f57ca1aa5c2 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -5,6 +5,9 @@ /* Specifies the compiler flag that forces a short wchar_t */ #undef CC_FLAG_SHORT_WCHAR +/* Define to 1 if you have the header file. */ +#undef HAVE_ALIAS_H + /* Define if you have ALSA 1.x including devel headers */ #undef HAVE_ALSA @@ -435,6 +438,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_ICMP_VAR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_H @@ -444,6 +453,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IN_SYSTM_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IP_ICMP_H + /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IP_VAR_H @@ -453,9 +468,18 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_TCP_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_TCP_TIMER_H + /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_TCP_VAR_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_UDP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_UDP_VAR_H + /* Define to 1 if you have the header file. */ #undef HAVE_NETIPX_IPX_H diff --git a/include/control.idl b/include/control.idl index af8a2f9e971..ddb52795b60 100644 --- a/include/control.idl +++ b/include/control.idl @@ -17,10 +17,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -cpp_quote("#if 0") /* FIXME: these files are not included on Windows */ -import "shldisp.idl"; -import "strmif.idl"; -cpp_quote("#endif") +import "oaidl.idl"; interface IMediaControl; interface IBasicAudio; @@ -34,6 +31,11 @@ typedef long OAFilterState; typedef LONG_PTR OAHWND; typedef LONG_PTR OAEVENT; +cpp_quote("#ifndef REFTIME_DEFINED") +cpp_quote("#define REFTIME_DEFINED") +typedef DOUBLE REFTIME; +cpp_quote("#endif") + /***************************************************************************** * IMediaControl interface */ diff --git a/include/dbt.h b/include/dbt.h index 0110e6cadbf..88a1df47ee5 100644 --- a/include/dbt.h +++ b/include/dbt.h @@ -142,4 +142,6 @@ typedef struct _DEV_BROADCAST_HANDLE BYTE dbch_data[1]; } DEV_BROADCAST_HANDLE, *PDEV_BROADCAST_HANDLE; +#undef DECL_WINELIB_DBT_TYPE_AW + #endif /* __WINE_DBT_H */ diff --git a/include/dsound.h b/include/dsound.h index b14229e2546..e1bd6680fc5 100644 --- a/include/dsound.h +++ b/include/dsound.h @@ -396,7 +396,7 @@ typedef const GUID *LPCGUID; typedef BOOL (CALLBACK *LPDSENUMCALLBACKW)(LPGUID,LPCWSTR,LPCWSTR,LPVOID); typedef BOOL (CALLBACK *LPDSENUMCALLBACKA)(LPGUID,LPCSTR,LPCSTR,LPVOID); -DECL_WINELIB_TYPE_AW(LPDSENUMCALLBACK); +DECL_WINELIB_TYPE_AW(LPDSENUMCALLBACK) extern HRESULT WINAPI DirectSoundCreate(LPCGUID lpGUID,LPDIRECTSOUND *ppDS,LPUNKNOWN pUnkOuter); extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA, LPVOID); diff --git a/include/gdiplusenums.h b/include/gdiplusenums.h index a27ed5e7b2e..8e1148d7847 100644 --- a/include/gdiplusenums.h +++ b/include/gdiplusenums.h @@ -250,6 +250,16 @@ enum StringTrimming StringTrimmingEllipsisPath = 5 }; +enum FontStyle +{ + FontStyleRegular = 0, + FontStyleBold = 1, + FontStyleItalic = 2, + FontStyleBoldItalic = 3, + FontStyleUnderline = 4, + FontStyleStrikeout = 8 +}; + enum HotkeyPrefix { HotkeyPrefixNone = 0, @@ -330,6 +340,7 @@ typedef enum CompositingMode CompositingMode; typedef enum TextRenderingHint TextRenderingHint; typedef enum StringAlignment StringAlignment; typedef enum StringTrimming StringTrimming; +typedef enum FontStyle FontStyle; typedef enum StringFormatFlags StringFormatFlags; typedef enum HotkeyPrefix HotkeyPrefix; typedef enum PenAlignment GpPenAlignment; diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h index 58659fedb27..09036375be6 100644 --- a/include/gdiplusflat.h +++ b/include/gdiplusflat.h @@ -49,6 +49,13 @@ GpStatus WINGDIPAPI GdipSetPenLineJoin(GpPen*,GpLineJoin); GpStatus WINGDIPAPI GdipSetPenMiterLimit(GpPen*,REAL); GpStatus WINGDIPAPI GdipSetPenStartCap(GpPen*,GpLineCap); GpStatus WINGDIPAPI GdipSetPenWidth(GpPen*,REAL); +GpStatus WINGDIPAPI GdipGetPenDashCap197819(GpPen*,GpDashCap*); +GpStatus WINGDIPAPI GdipGetPenEndCap(GpPen*,GpLineCap*); +GpStatus WINGDIPAPI GdipGetPenLineJoin(GpPen*,GpLineJoin*); +GpStatus WINGDIPAPI GdipGetPenMiterLimit(GpPen*,REAL*); +GpStatus WINGDIPAPI GdipGetPenStartCap(GpPen*,GpLineCap*); +GpStatus WINGDIPAPI GdipGetPenUnit(GpPen*,GpUnit*); +GpStatus WINGDIPAPI GdipGetPenWidth(GpPen*,REAL*); GpStatus WINGDIPAPI GdipCreateFromHDC(HDC,GpGraphics**); GpStatus WINGDIPAPI GdipCreateFromHDC2(HDC,HANDLE,GpGraphics**); @@ -146,6 +153,8 @@ GpStatus WINGDIPAPI GdipSetCompositingQuality(GpGraphics*,CompositingQuality); GpStatus WINGDIPAPI GdipSetInterpolationMode(GpGraphics*,InterpolationMode); GpStatus WINGDIPAPI GdipSetPageScale(GpGraphics*,REAL); GpStatus WINGDIPAPI GdipSetPageUnit(GpGraphics*,GpUnit); +GpStatus WINGDIPAPI GdipSetPathMarker(GpPath*); +GpStatus WINGDIPAPI GdipClearPathMarkers(GpPath*); GpStatus WINGDIPAPI GdipSetPixelOffsetMode(GpGraphics*,PixelOffsetMode); GpStatus WINGDIPAPI GdipSetSmoothingMode(GpGraphics*,SmoothingMode); GpStatus WINGDIPAPI GdipSetTextRenderingHint(GpGraphics*,TextRenderingHint); @@ -213,6 +222,8 @@ GpStatus WINGDIPAPI GdipAddPathLine2(GpPath*,GDIPCONST GpPointF*,INT); GpStatus WINGDIPAPI GdipAddPathLine2I(GpPath*,GDIPCONST GpPoint*,INT); GpStatus WINGDIPAPI GdipAddPathLineI(GpPath*,INT,INT,INT,INT); GpStatus WINGDIPAPI GdipAddPathPath(GpPath*,GDIPCONST GpPath*,BOOL); +GpStatus WINGDIPAPI GdipAddPathPolygon(GpPath*,GDIPCONST GpPointF*,INT); +GpStatus WINGDIPAPI GdipAddPathPolygonI(GpPath*,GDIPCONST GpPoint*,INT); GpStatus WINGDIPAPI GdipAddPathRectangle(GpPath*,REAL,REAL,REAL,REAL); GpStatus WINGDIPAPI GdipAddPathRectangleI(GpPath*,INT,INT,INT,INT); GpStatus WINGDIPAPI GdipAddPathRectangles(GpPath*,GDIPCONST GpRectF*,INT); @@ -269,6 +280,7 @@ GpStatus WINGDIPAPI GdipPathIterCopyData(GpPathIterator*,INT*,GpPointF*,BYTE*, INT,INT); GpStatus WINGDIPAPI GdipPathIterNextSubpath(GpPathIterator*,INT*,INT*,INT*,BOOL*); GpStatus WINGDIPAPI GdipPathIterRewind(GpPathIterator*); +GpStatus WINGDIPAPI GdipPathIterGetCount(GpPathIterator*,INT*); GpStatus WINGDIPAPI GdipCloneCustomLineCap(GpCustomLineCap*,GpCustomLineCap**); GpStatus WINGDIPAPI GdipCreateCustomLineCap(GpPath*,GpPath*,GpLineCap,REAL, @@ -318,6 +330,7 @@ GpStatus WINGDIPAPI GdipGetMetafileHeaderFromStream(IStream*,MetafileHeader*); GpStatus WINGDIPAPI GdipGetMetafileHeaderFromWmf(HMETAFILE,GDIPCONST WmfPlaceableFileHeader*,MetafileHeader*); GpStatus WINGDIPAPI GdipGetPropertyItemSize(GpImage*,PROPID,UINT*); GpStatus WINGDIPAPI GdipImageGetFrameCount(GpImage*,GDIPCONST GUID*,UINT*); +GpStatus WINGDIPAPI GdipImageGetFrameDimensionsCount(GpImage*,UINT*); GpStatus WINGDIPAPI GdipImageGetFrameDimensionsList(GpImage*,GUID*,UINT); GpStatus WINGDIPAPI GdipImageSelectActiveFrame(GpImage*,GDIPCONST GUID*,UINT); GpStatus WINGDIPAPI GdipLoadImageFromFile(GDIPCONST WCHAR*,GpImage**); @@ -330,6 +343,7 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage*,IStream*, GDIPCONST CLSID*,GDIPCONST EncoderParameters*); GpStatus WINGDIPAPI GdipSetImagePalette(GpImage*,GDIPCONST ColorPalette*); +GpStatus WINGDIPAPI GdipCloneImageAttributes(GDIPCONST GpImageAttributes*,GpImageAttributes**); GpStatus WINGDIPAPI GdipCreateImageAttributes(GpImageAttributes**); GpStatus WINGDIPAPI GdipDisposeImageAttributes(GpImageAttributes*); GpStatus WINGDIPAPI GdipSetImageAttributesColorKeys(GpImageAttributes*, @@ -340,12 +354,25 @@ GpStatus WINGDIPAPI GdipSetImageAttributesColorMatrix(GpImageAttributes*, GpStatus WINGDIPAPI GdipSetImageAttributesWrapMode(GpImageAttributes*,WrapMode, ARGB,BOOL); +GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily*, REAL, INT, Unit, + GpFont**); GpStatus WINGDIPAPI GdipCreateFontFromDC(HDC,GpFont**); GpStatus WINGDIPAPI GdipCreateFontFromLogfontA(HDC,GDIPCONST LOGFONTA*,GpFont**); GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC,GDIPCONST LOGFONTW*,GpFont**); GpStatus WINGDIPAPI GdipDeleteFont(GpFont*); GpStatus WINGDIPAPI GdipGetLogFontW(GpFont*,GpGraphics*,LOGFONTW*); GpStatus WINGDIPAPI GdipCloneFont(GpFont*,GpFont**); +GpStatus WINGDIPAPI GdipGetFontUnit(GpFont*, Unit*); +GpStatus WINGDIPAPI GdipGetFontSize(GpFont*, REAL*); + +GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR*, + GpFontCollection*, GpFontFamily**); +GpStatus WINGDIPAPI GdipDeleteFontFamily(GpFontFamily*); +GpStatus WINGDIPAPI GdipGetFamilyName(GDIPCONST GpFontFamily*, WCHAR*, LANGID); + +GpStatus WINGDIPAPI GdipGetGenericFontFamilySansSerif(GpFontFamily**); +GpStatus WINGDIPAPI GdipGetGenericFontFamilySerif(GpFontFamily**); +GpStatus WINGDIPAPI GdipGetGenericFontFamilyMonospace(GpFontFamily**); GpStatus WINGDIPAPI GdipCreateStringFormat(INT,LANGID,GpStringFormat**); GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat*); diff --git a/include/gdiplusgpstubs.h b/include/gdiplusgpstubs.h index c5e676d6440..e2f8ab7e0ce 100644 --- a/include/gdiplusgpstubs.h +++ b/include/gdiplusgpstubs.h @@ -37,6 +37,8 @@ class GpPathGradient : public GpBrush {}; class GpLineGradient : public GpBrush {}; class GpTexture : public GpBrush {}; class GpFont {}; +class GpFontCollection {}; +class GpFontFamily {}; class GpStringFormat {}; class GpRegion {}; class CGpEffect {}; @@ -59,6 +61,8 @@ typedef struct GpPathGradient GpPathGradient; typedef struct GpLineGradient GpLineGradient; typedef struct GpTexture GpTexture; typedef struct GpFont GpFont; +typedef struct GpFontCollection GpFontCollection; +typedef struct GpFontFamily GpFontFamily; typedef struct GpStringFormat GpStringFormat; typedef struct GpRegion GpRegion; typedef struct CGpEffect CGpEffect; diff --git a/include/iprtrmib.h b/include/iprtrmib.h index ba84cc5ad5b..cf2bb24db34 100644 --- a/include/iprtrmib.h +++ b/include/iprtrmib.h @@ -261,6 +261,10 @@ typedef struct _MIB_IPNETROW DWORD dwType; } MIB_IPNETROW, *PMIB_IPNETROW; +#define MIB_TCP_RTO_OTHER 1 +#define MIB_TCP_RTO_CONSTANT 2 +#define MIB_TCP_RTO_RSRE 3 +#define MIB_TCP_RTO_VANJ 4 #define MIB_IPNET_TYPE_OTHER 1 #define MIB_IPNET_TYPE_INVALID 2 #define MIB_IPNET_TYPE_DYNAMIC 3 diff --git a/include/msinkaut.idl b/include/msinkaut.idl index 1f221749a4c..607229d8c50 100644 --- a/include/msinkaut.idl +++ b/include/msinkaut.idl @@ -28,6 +28,86 @@ library MSINKAUTLib typedef float single; + typedef enum InkBoundingBoxMode { + IBBM_Default = 0, + IBBM_NoCurveFit = 1, + IBBM_CurveFit = 2, + IBBM_PointsOnly = 3, + IBBM_Union = 4 + } InkBoundingBoxMode; + + typedef enum InkExtractFlags { + IEF_CopyFromOriginal = 0x0, + IEF_RemoveFromOriginal = 0x1, + IEF_Default = IEF_RemoveFromOriginal + } InkExtractFlags; + + typedef enum InkPersistenceFormat { + IPF_InkSerializeFormat = 0, + IPF_Base64InkSerializedFormat = 1, + IPF_GIF = 2, + IPF_Base64GIF = 3 + } InkPersistenceFormat; + + typedef enum InkPersistenceCompressionMode + { + IPCM_Default = 0, + IPCM_MaximumCompression = 1, + IPCM_NoCompression = 2 + } InkPersistenceCompressionMode; + + typedef enum InkPenTip { + IPT_Ball = 0, + IPT_Rectangle = 1 + } InkPenTip; + + typedef enum InkRasterOperation { + IRO_Black = 1, + IRO_NotMergePen, + IRO_MaskNotPen, + IRO_NotCopyPen, + IRO_MaskPenNot, + IRO_Not, + IRO_XOrPen, + IRO_NotMaskPen, + IRO_MaskPen, + IRO_NotXOrPen, + IRO_NoOperation, + IRO_MergeNotPen, + IRO_CopyPen, + IRO_MergePenNot, + IRO_MergePen, + IRO_White + } InkRasterOperation; + + typedef enum InkClipboardModes { + ICB_Copy = 0, + ICB_Cut = 0x1, + ICB_DelayedCopy = 0x20, + ICB_ExtractOnly = 0x30, + ICB_Default = ICB_Copy + } InkClipboardModes; + + typedef enum InkClipboardFormats { + ICF_None = 0, + ICF_InkSerializedFormat = 0x1, + ICF_SketchInk = 0x2, + ICF_TextInk = 0x6, + ICF_EnhancedMetafile = 0x8, + ICF_Metafile = 0x20, + ICF_Bitmap = 0x40, + ICF_PasteMask = 0x7, + ICF_CopyMask = 0x7f, + ICF_Default = ICF_CopyMask + } InkClipboardFormats; + + typedef enum InkRecognitionConfidence + { + IRC_Strong = 0, + IRC_Intermediate = 1, + IRC_Poor = 2 + } InkRecognitionConfidence; + [ odl, uuid(DB489209-B7C3-411D-90F6-1548CFFF271E), @@ -63,30 +143,6 @@ library MSINKAUTLib [out, retval] VARIANT_BOOL* DoesPropertyExist); }; - typedef enum { - IRO_Black = 1, - IRO_NotMergePen, - IRO_MaskNotPen, - IRO_NotCopyPen, - IRO_MaskPenNot, - IRO_Not, - IRO_XOrPen, - IRO_NotMaskPen, - IRO_MaskPen, - IRO_NotXOrPen, - IRO_NoOperation, - IRO_MergeNotPen, - IRO_CopyPen, - IRO_MergePenNot, - IRO_MergePen, - IRO_White - } InkRasterOperation; - - typedef enum { - IPT_Ball, - IPT_Rectangle - } InkPenTip; - [ odl, uuid(BF519B75-0A15-4623-ADC9-C00D436A8092), @@ -205,14 +261,6 @@ cpp_quote("#endif /* _WINGDI_ */") interface IInkDisp; - typedef enum { - IBBM_Default, - IBBM_NoCurveFit, - IBBM_CurveFit, - IBBM_PointsOnly, - IBBM_Union - } InkBoundingBoxMode; - [ odl, uuid(9794FF82-6071-4717-8A8B-6AC7C64A686E), @@ -364,6 +412,270 @@ cpp_quote("#endif /* _WINGDI_ */") [in] single VerticalMultiplier); }; + interface IInkRecognitionResult; + + [ + odl, + uuid(F1F4C9D8-590A-4963-B3AE-1935671BB6F3), + dual, + oleautomation + ] + interface IInkStrokes : IDispatch { + [propget] HRESULT Count( + [out, retval] long *Count); + [propget, restricted] HRESULT _NewEnum( + [out, retval] IUnknown **_NewEnum); + [propget] HRESULT Ink( + [out, retval] IInkDisp **Ink); + [propget] HRESULT RecognitionResult( + [out, retval] IInkRecognitionResult **RecognitionResult); + HRESULT ToString( + [out, retval] BSTR *ToString); + HRESULT Item( + [in] long Index, + [out, retval] IInkStrokeDisp **Stroke); + HRESULT Add( + [in] IInkStrokeDisp *InkStroke); + HRESULT AddStrokes( + [in] IInkStrokes *InkStrokes); + HRESULT Remove( + [in] IInkStrokeDisp *InkStroke); + HRESULT RemoveStrokes( + [in] IInkStrokes *InkStrokes); + HRESULT ModifyDrawingAttributes( + [in] IInkDrawingAttributes *DrawAttrs); + HRESULT GetBoundingBox( + [in] InkBoundingBoxMode BoundingBoxMode, + [out, retval] IInkRectangle **BoundingBox); + HRESULT Transform( + [in] IInkTransform *Transform, + [in] VARIANT_BOOL ApplyOnPenWidth); + HRESULT ScaleToRectangle( + [in] IInkRectangle *Rectangle); + HRESULT Move( + [in] float HorizontalComponent, + [in] float VerticalComponent); + HRESULT Rotate( + [in] float Degrees, + [in] float x, + [in] float y); + HRESULT Shear( + [in] float HorizontalMultiplier, + [in] float VerticalMultiplier); + HRESULT ScaleTransform( + [in] float HorizontalMultiplier, + [in] float VerticalMultiplier); + HRESULT Clip( + [in] IInkRectangle *Rectangle); + HRESULT RemoveRecognitionResult(); + }; + + [ + odl, + uuid(7E23A88F-C30E-420f-9BDB-28902543F0C1), + dual, + oleautomation + ] + interface IInkCustomStrokes : IDispatch { + [propget] HRESULT Count( + [out, retval] long *Count); + [propget] HRESULT _NewEnum( + [out, retval] IUnknown **_NewEnum); + HRESULT Item( + [in] VARIANT Identifier, + [out, retval] IInkStrokes **Strokes); + HRESULT Add( + [in] BSTR Name, + [in] IInkStrokes *Strokes); + HRESULT Remove( + [in] VARIANT Identifier); + HRESULT Clear(); + }; + + interface IInkRecognitionAlternate; + interface IInkRecognitionAlternates; + + [ + odl, + uuid(3BC129A8-86CD-45ad-BDE8-E0D32D61C16D), + dual, + oleautomation + ] + interface IInkRecognitionResult : IDispatch { + [propget] HRESULT TopString( + [out, retval] BSTR *TopString); + [propget] HRESULT TopAlternate( + [out, retval] IInkRecognitionAlternate **TopAlternate); + [propget] HRESULT TopConfidence( + [out, retval] InkRecognitionConfidence *TopConfidence); + [propget] HRESULT Strokes( + [out, retval] IInkStrokes **Strokes); + HRESULT AlternatesFromSelection( + [in] long selectionStart, + [in] long selectionLength, + [in] long maximumAlternates, + [out, retval] IInkRecognitionAlternates **AlternatesFromSelection); + HRESULT ModifyTopAlternate( + [in] IInkRecognitionAlternate *Alternate); + HRESULT SetResultOnStrokes(); + }; + + [ + odl, + uuid(B7E660AD-77E4-429b-ADDA-873780D1FC4A), + dual, + oleautomation + ] + interface IInkRecognitionAlternate : IDispatch { + [propget] HRESULT String( + [out, retval] BSTR *RecoString); + [propget] HRESULT Confidence( + [out, retval] InkRecognitionConfidence *Confidence); + [propget] HRESULT Baseline( + [out, retval] VARIANT *Baseline); + [propget] HRESULT Midline( + [out, retval] VARIANT *Midline); + [propget] HRESULT Ascender( + [out, retval] VARIANT *Ascender); + [propget] HRESULT Descender( + [out, retval] VARIANT *Descender); + [propget] HRESULT LineNumber( + [out, retval] long *LineNumber); + [propget] HRESULT Strokes( + [out, retval] IInkStrokes **Strokes); + [propget] HRESULT LineAlternates( + [out, retval] IInkRecognitionAlternates **LineAlternates); + [propget] HRESULT ConfidenceAlternates( + [out, retval] IInkRecognitionAlternates **ConfidenceAlternates); + HRESULT GetStrokesFromStrokeRanges( + [in] IInkStrokes *Stroke, + [out, retval] IInkStrokes **GetStrokesFromTextRange); + HRESULT GetStrokesFromTextRange( + [in, out] long *selectionStart, + [in, out] long *selectionLength, + [out, retval] IInkStrokes **GetStrokesFromTextRange); + HRESULT GetTextRangeFromStrokes( + [in] IInkStrokes *Strokes, + [in, out] long *selectionStart, + [in, out] long *selectionLength); + HRESULT AlternatesWithConstantPropertyValues( + [in] BSTR PropertyType, + [out, retval] IInkRecognitionAlternates **AlternatesWithConstantPropertyValues); + HRESULT GetPropertyValue( + [in] BSTR PropertyType, + [out, retval] VARIANT *PropertyValue); + }; + + [ + odl, + uuid(286A167F-9F19-4c61-9D53-4F07BE622B84), + dual, + oleautomation + ] + interface IInkRecognitionAlternates : IDispatch { + [propget] HRESULT Count( + [out, retval] long *Count); + [propget, restricted] HRESULT _NewEnum( + [out, retval] IUnknown **_NewEnum); + [propget] HRESULT Strokes( + [out, retval] IInkStrokes **Strokes); + HRESULT Item( + [in] long Index, + [out, retval] IInkRecognitionAlternate **InkRecoAlternate); + }; + + [ + odl, + uuid(9D398FA0-C4E2-4fcd-9973-975CAAF47EA6), + dual, + oleautomation + ] + interface IInkDisp : IDispatch { + [propget] HRESULT Strokes( + [out, retval] IInkStrokes **Strokes); + [propget] HRESULT ExtendedProperties( + [out, retval] IInkExtendedProperties **Properties); + [propget] HRESULT Dirty( + [out, retval] VARIANT_BOOL *Dirty); + [propput] HRESULT Dirty( + [in] VARIANT_BOOL Dirty); + [propget] HRESULT CustomStrokes( + [out, retval] IInkCustomStrokes **CustomStrokes); + HRESULT GetBoundingBox( + [in] InkBoundingBoxMode BoundingBoxMode, + [out] IInkRectangle **Rectangle); + HRESULT DeleteStrokes( + [in, unique] IInkStrokes *Strokes); + HRESULT DeleteStroke( + [in] IInkStrokeDisp *Stroke); + HRESULT ExtractStrokes( + [in] IInkStrokes *Strokes, + [in] InkExtractFlags ExtractFlags, + [out, retval] IInkDisp **ExtractedInk); + HRESULT ExtractWithRectangle( + [in] IInkRectangle *Rectangle, + [in] InkExtractFlags ExtractFlags, + [out, retval] IInkDisp **ExtractedInk); + HRESULT Clip( + [in] IInkRectangle *Rectangle); + HRESULT Clone( + [out, retval] IInkDisp **NewInk); + HRESULT HitTestCircle( + [in] long X, + [in] long Y, + [in] float radius, + [out, retval] IInkStrokes **Strokes); + HRESULT HitTestWithRectangle( + [in] IInkRectangle *SelectionRectangle, + [in] float IntersectPercent, + [out, retval] IInkStrokes **Strokes); + HRESULT HitTestWithLasso( + [in] VARIANT Points, + [in] float IntersectPercent, + [in, out, unique] VARIANT *LassoPoints, + [out, retval] IInkStrokes **Strokes); + HRESULT NearestPoint( + [in] long X, + [in] long Y, + [in, out] float PointOnStroke, + [in, out] float DistanceFromPacket, + [out, retval] IInkStrokeDisp **Stroke); + HRESULT CreateStrokes( + [in] VARIANT StrokeIds, + [out, retval] IInkStrokes **Strokes); + HRESULT AddStrokesAtRectangle( + [in] IInkStrokes *SourceStrokes, + [in] IInkRectangle *TargetRectangle); + HRESULT Save( + [in] InkPersistenceFormat PersistenceFormat, + [in] InkPersistenceCompressionMode CompressionMode, + [out, retval] VARIANT *Data); + HRESULT Load( + [in] VARIANT Data); + HRESULT CreateStroke( + [in] VARIANT PacketData, + [in] VARIANT PacketDescription, + [out, retval] IInkStrokeDisp **Stroke); + HRESULT ClipboardCopyWithRectangle( + [in] IInkRectangle *Rectangle, + [in] InkClipboardFormats ClipboardFormats, + [in] InkClipboardModes ClipboardModes, + [out, retval] IDataObject **DataObject); + HRESULT ClipboardCopy( + [in] IInkStrokes *strokes, + [in] InkClipboardFormats ClipboardFormats, + [in] InkClipboardModes ClipboardModes, + [out, retval] IDataObject **DataObject); + HRESULT CanPaste( + [in] IDataObject *DataObject, + [out, retval] VARIANT_BOOL *CanPaste); + HRESULT ClipboardPaste( + [in] long x, + [in] long y, + [in, unique] IDataObject *DataObject, + [out, retval] IInkStrokes **Strokes); + }; + [ odl, uuid(E6257A9C-B511-4F4C-A8B0-A7DBC9506B83), diff --git a/include/ole2.h b/include/ole2.h index 5617c835faf..a92c2f4ee0e 100644 --- a/include/ole2.h +++ b/include/ole2.h @@ -84,6 +84,7 @@ HRESULT WINAPI OleCreateLinkFromData(LPDATAOBJECT pSrcDataObj, REFIID riid, LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID* ppvObj); HRESULT WINAPI OleSetContainedObject(LPUNKNOWN pUnknown, BOOL fContained); +HRESULT WINAPI OleNoteObjectVisible(LPUNKNOWN pUnknown, BOOL fVisible); HRESULT WINAPI OleQueryLinkFromData(IDataObject* pSrcDataObject); HRESULT WINAPI OleQueryCreateFromData(LPDATAOBJECT pSrcDataObject); HRESULT WINAPI OleRun(LPUNKNOWN pUnknown); @@ -111,6 +112,7 @@ HRESULT WINAPI OleCreateLink(LPMONIKER pmkLinkSrc, REFIID riid, DWORD render HRESULT WINAPI OleCreate(REFCLSID rclsid, REFIID riid, DWORD renderopt, LPFORMATETC pFormatEtc, LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID* ppvObj); HRESULT WINAPI OleFlushClipboard(void); +HRESULT WINAPI GetConvertStg(LPSTORAGE pStg); HRESULT WINAPI SetConvertStg(LPSTORAGE pStg, BOOL fConvert); BOOL WINAPI IsAccelerator(HACCEL hAccel, int cAccelEntries, struct tagMSG* lpMsg, WORD* lpwCmd); HRESULT WINAPI OleCreateLinkToFile(LPCOLESTR lpszFileName, REFIID riid, DWORD renderopt, LPFORMATETC lpFormatEtc, @@ -154,6 +156,7 @@ typedef struct _OLESTREAM { HRESULT WINAPI OleConvertOLESTREAMToIStorage( LPOLESTREAM lpolestream, LPSTORAGE pstg, const DVTARGETDEVICE* ptd); HRESULT WINAPI OleConvertIStorageToOLESTREAM( LPSTORAGE pstg, LPOLESTREAM lpolestream); +HRESULT WINAPI OleDoAutoConvert( LPSTORAGE pStg, LPCLSID pClsidNew ); HRESULT WINAPI OleGetAutoConvert( REFCLSID clsidOld, LPCLSID pClsidNew ); HRESULT WINAPI OleSetAutoConvert( REFCLSID clsidOld, REFCLSID clsidNew ); diff --git a/include/richedit.h b/include/richedit.h index 3213a75e0d1..f4f0ab5da00 100644 --- a/include/richedit.h +++ b/include/richedit.h @@ -56,6 +56,26 @@ static const WCHAR RICHEDIT_CLASS20W[] = { 'R','i','c','h','E','d','i','t','2',' #define RICHEDIT_CLASS RICHEDIT_CLASS10A #endif +#ifndef WM_NOTIFY +#define WM_NOTIFY 0x004e +#endif +#ifndef WM_CONTEXTMENU +#define WM_CONTEXTMENU 0x007b +#endif +#ifndef WM_UNICHAR +#define WM_UNICHAR 0x0109 +#endif +#ifndef WM_PRINTCLIENT +#define WM_PRINTCLIENT 0x0318 +#endif + +#ifndef EM_GETLIMITTEXT +#define EM_GETLIMITTEXT (WM_USER + 37) +#endif +#ifndef EM_POSFROMCHAR +#define EM_POSFROMCHAR (WM_USER + 38) +#define EM_CHARFROMPOS (WM_USER + 39) +#endif #ifndef EM_SCROLLCARET #define EM_SCROLLCARET (WM_USER + 49) #endif @@ -147,6 +167,24 @@ static const WCHAR RICHEDIT_CLASS20W[] = { 'R','i','c','h','E','d','i','t','2',' #define EM_SETFONTSIZE (WM_USER + 223) #define EM_GETZOOM (WM_USER + 224) #define EM_SETZOOM (WM_USER + 225) +#define EM_GETVIEWKIND (WM_USER + 226) +#define EM_SETVIEWKIND (WM_USER + 227) + +#define EM_GETPAGE (WM_USER + 228) +#define EM_SETPAGE (WM_USER + 229) +#define EM_GETHYPHENATEINFO (WM_USER + 230) +#define EM_SETHYPHENATEINFO (WM_USER + 231) +#define EM_GETPAGEROTATE (WM_USER + 235) +#define EM_SETPAGEROTATE (WM_USER + 236) +#define EM_GETCTFMODEBIAS (WM_USER + 237) +#define EM_SETCTFMODEBIAS (WM_USER + 238) +#define EM_GETCTFOPENSTATUS (WM_USER + 240) +#define EM_SETCTFOPENSTATUS (WM_USER + 241) +#define EM_GETIMECOMPTEXT (WM_USER + 242) +#define EM_ISIME (WM_USER + 243) +#define EM_GETIMEPROPERTY (WM_USER + 244) +#define EM_GETQUERYRTFOBJ (WM_USER + 269) +#define EM_SETQUERYRTFOBJ (WM_USER + 270) /* New notifications */ #define EN_MSGFILTER 0x0700 @@ -163,16 +201,25 @@ static const WCHAR RICHEDIT_CLASS20W[] = { 'R','i','c','h','E','d','i','t','2',' #define EN_LINK 0x070b #define EN_DRAGDROPDONE 0x070c #define EN_PARAGRAPHEXPANDED 0x070d +#define EN_PAGECHANGE 0x070e +#define EN_LOWFIRTF 0x070f #define EN_ALIGNLTR 0x0710 #define EN_ALIGNRTL 0x0711 typedef DWORD (CALLBACK * EDITSTREAMCALLBACK)( DWORD_PTR, LPBYTE, LONG, LONG * ); + +#define yHeightCharPtsMost 1638 +#define lDefaultTab 720 + /* tab stops number limit */ #define MAX_TAB_STOPS 0x00000020 +#define MAX_TABLE_CELLS 63 + /* Rich edit control styles */ +#define ES_NOOLEDRAGDROP 0x00000008 #define ES_DISABLENOSCROLL 0x00002000 #define ES_SUNKEN 0x00004000 #define ES_SAVESEL 0x00008000 @@ -188,6 +235,18 @@ typedef DWORD (CALLBACK * EDITSTREAMCALLBACK)( DWORD_PTR, LPBYTE, LONG, LONG * ) #define SCF_WORD 0x00000002 #define SCF_ALL 0x00000004 #define SCF_USEUIRULES 0x00000008 +#define SCF_ASSOCIATEFONT 0x00000010 +#define SCF_NOKBUPDATE 0x00000020 +#define SCF_ASSOCIATEFONT2 0x00000040 + +#ifndef WM_NOTIFY +typedef struct _nmhdr +{ + HWND hwndFrom; + UINT idFrom; + UINT code; +} NMHDR; +#endif /* CHARFORMAT structure */ typedef struct _charformat @@ -264,6 +323,8 @@ typedef struct _charformat2w { DECL_WINELIB_TYPE_AW(CHARFORMAT2) +#define CHARFORMATDELTA (sizeof(CHARFORMAT2) - sizeof(CHARFORMAT)) + /* CHARFORMAT masks */ #define CFM_BOLD 0x00000001 #define CFM_ITALIC 0x00000002 @@ -296,7 +357,47 @@ DECL_WINELIB_TYPE_AW(CHARFORMAT2) #define CFM_FACE 0x20000000 #define CFM_COLOR 0x40000000 #define CFM_SIZE 0x80000000 -#define CFM_EFFECTS (CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_COLOR | CFM_STRIKEOUT | CFE_PROTECTED | CFM_LINK) + +#define CFM_EFFECTS (CFM_BOLD | \ + CFM_ITALIC | \ + CFM_UNDERLINE | \ + CFM_COLOR | \ + CFM_STRIKEOUT | \ + CFE_PROTECTED | \ + CFM_LINK) + +#define CFM_EFFECTS2 (CFM_EFFECTS | \ + CFM_DISABLED | \ + CFM_SMALLCAPS | \ + CFM_ALLCAPS | \ + CFM_HIDDEN | \ + CFM_OUTLINE | \ + CFM_SHADOW | \ + CFM_EMBOSS | \ + CFM_IMPRINT | \ + CFM_DISABLED | \ + CFM_REVISED | \ + CFM_SUBSCRIPT | \ + CFM_SUPERSCRIPT | \ + CFM_BACKCOLOR) + +#define CFM_ALL (CFM_EFFECTS | \ + CFM_SIZE | \ + CFM_FACE | \ + CFM_OFFSET | \ + CFM_CHARSET) + +#define CFM_ALL2 (CFM_ALL | \ + CFM_EFFECTS2 | \ + CFM_BACKCOLOR | \ + CFM_LCID | \ + CFM_UNDERLINETYPE | \ + CFM_WEIGHT | \ + CFM_REVAUTHOR | \ + CFM_SPACING | \ + CFM_KERNING | \ + CFM_STYLE | \ + CFM_ANIMATION) /* CHARFORMAT effects */ #define CFE_BOLD 0x00000001 @@ -320,13 +421,27 @@ DECL_WINELIB_TYPE_AW(CHARFORMAT2) #define CFE_REVISED CFM_REVISED #define CFE_AUTOBACKCOLOR CFM_BACKCOLOR -#define CFU_CF1UNDERLINE 0xFF -#define CFU_INVERT 0xFE -#define CFU_UNDERLINEDOTTED 0x04 -#define CFU_UNDERLINEDOUBLE 0x03 -#define CFU_UNDERLINEWORD 0x02 -#define CFU_UNDERLINE 0x01 -#define CFU_UNDERLINENONE 0x00 +#define CFU_UNDERLINENONE 0x00 +#define CFU_UNDERLINE 0x01 +#define CFU_UNDERLINEWORD 0x02 +#define CFU_UNDERLINEDOUBLE 0x03 +#define CFU_UNDERLINEDOTTED 0x04 +#define CFU_UNDERLINEDASH 0x05 +#define CFU_UNDERLINEDASHDOT 0x06 +#define CFU_UNDERLINEDASHDOTDOT 0x07 +#define CFU_UNDERLINEWAVE 0x08 +#define CFU_UNDERLINETHICK 0x09 +#define CFU_UNDERLINEHAIRLINE 0x0a +#define CFU_UNDERLINEDOUBLEWAVE 0x0b +#define CFU_UNDERLINEHEAVYWAVE 0x0c +#define CFU_UNDERLINELONGDASH 0x0d +#define CFU_UNDERLINETHICKDASH 0x0e +#define CFU_UNDERLINETHICKDASHDOT 0x0f +#define CFU_UNDERLINETHICKDASHDOTDOT 0x10 +#define CFU_UNDERLINETHICKDOTTED 0x11 +#define CFU_UNDERLINETHICKLONGDASH 0x12 +#define CFU_INVERT 0xFE +#define CFU_CF1UNDERLINE 0xFF /* ECO operations */ #define ECOOP_SET 0x0001 @@ -350,6 +465,10 @@ DECL_WINELIB_TYPE_AW(CHARFORMAT2) #define ENM_CHANGE 0x00000001 #define ENM_UPDATE 0x00000002 #define ENM_SCROLL 0x00000004 +#define ENM_SCROLLEVENTS 0x00000008 +#define ENM_DRAGDROPDONE 0x00000010 +#define ENM_PARAGRAPHEXPANDED 0x00000020 +#define ENM_PAGECHANGE 0x00000040 #define ENM_KEYEVENTS 0x00010000 #define ENM_MOUSEEVENTS 0x00020000 #define ENM_REQUESTRESIZE 0x00040000 @@ -358,7 +477,17 @@ DECL_WINELIB_TYPE_AW(CHARFORMAT2) #define ENM_PROTECTED 0x00200000 #define ENM_CORRECTTEXT 0x00400000 #define ENM_IMECHANGE 0x00800000 +#define ENM_LANGCHANGE 0x01000000 +#define ENM_OBJECTPOSITIONS 0x02000000 #define ENM_LINK 0x04000000 +#define ENM_LOWFIRTF 0x08000000 + +typedef struct _bidioptions +{ + UINT cbSize; + WORD wMask; + WORD wEffects; +} BIDIOPTIONS; #ifndef __RICHEDIT_CHARRANGE_DEFINED #define __RICHEDIT_CHARRANGE_DEFINED @@ -419,6 +548,11 @@ typedef struct _enlink { CHARRANGE chrg; } ENLINK; +typedef struct _enlowfirtf { + NMHDR nmhdr; + char *szControl; +} ENLOWFIRTF; + typedef struct { NMHDR nmhdr; LONG iob; @@ -474,6 +608,31 @@ typedef struct _formatrange { CHARRANGE chrg; } FORMATRANGE; +typedef enum tagKHYPH +{ + khyphNil = 0, + khyphNormal = 1, + khyphAddBefore = 2, + khyphChangeBefore = 3, + khyphDeleteBefore = 4, + khyphChangeAfter = 5, + khyphDelAndChange = 6 +} KHYPH; + +typedef struct hyphresult +{ + KHYPH khyph; + long ichHyph; + WCHAR chHyph; +} HYPHRESULT; + +typedef struct tagHyphenateInfo +{ + SHORT cbSize; + SHORT dxHyphenateZone; + void (WINAPI* pfnHyphenate)(WCHAR*, LANGID, long, HYPHRESULT*); +} HYPHENATEINFO; + typedef struct _msgfilter { NMHDR nmhdr; UINT msg; @@ -481,6 +640,12 @@ typedef struct _msgfilter { LPARAM lParam; } MSGFILTER; +typedef struct _objectpositions { + NMHDR nmhdr; + LONG cObjectCount; + LONG *pcpPositions; +} OBJECTPOSITIONS; + typedef struct _paraformat { UINT cbSize; DWORD dwMask; @@ -542,6 +707,13 @@ typedef struct _gettextex { LPBOOL lpUsedDefChar; } GETTEXTEX; +typedef struct _imecomptext { + LONG cb; + DWORD flags; +} IMECOMPTEXT; + +void WINAPI HyphenateProc(WCHAR*, LANGID, long, HYPHRESULT*); + #define SF_TEXT 0x00000001 #define SF_RTF 0x00000002 #define SF_RTFNOOBJS 0x00000003 @@ -551,11 +723,86 @@ typedef struct _gettextex { #define SF_NCRFORNONASCII 0x00000040 #define SF_RTFVAL 0x00000700 +/* BIDIOPTIONS.wMask flag values */ +#define BOM_DEFPARADIR 0x00000001 +#define BOM_PLAINTEXT 0x00000002 +#define BOM_NEUTRALOVERRIDE 0x00000004 +#define BOM_CONTEXTREADING 0x00000008 +#define BOM_CONTEXTALIGNMENT 0x00000010 +#define BOM_LEGACYBIDICLASS 0x00000040 + +/* BIDIOPTIONS.wEffects flag values */ +#define BOE_RTLDIR 0x00000001 +#define BOE_PLAINTEXT 0x00000002 +#define BOE_NEUTRALOVERRIDE 0x00000004 +#define BOE_CONTEXTREADING 0x00000008 +#define BOE_CONTEXTALIGNMENT 0x00000010 +#define BOE_LEGACYBIDICLASS 0x00000040 + /* Clipboard formats */ #define CF_RTF TEXT("Rich Text Format") #define CF_RTFNOOBJS TEXT("Rich Text Format Without Objects") #define CF_RETEXTOBJ TEXT("RichEdit Text and Objects") +/* Mode bias wParam values for EM_SETCTFMODEBIAS message */ +#define CTFMODEBIAS_DEFAULT 0x00000000 +#define CTFMODEBIAS_FILENAME 0x00000001 +#define CTFMODEBIAS_NAME 0x00000002 +#define CTFMODEBIAS_READING 0x00000003 +#define CTFMODEBIAS_DATETIME 0x00000004 +#define CTFMODEBIAS_CONVERSATION 0x00000005 +#define CTFMODEBIAS_NUMERIC 0x00000006 +#define CTFMODEBIAS_HIRAGANA 0x00000007 +#define CTFMODEBIAS_KATAKANA 0x00000008 +#define CTFMODEBIAS_HANGUL 0x00000009 +#define CTFMODEBIAS_HALFWIDTHKATAKANA 0x0000000a +#define CTFMODEBIAS_FULLWIDTHALPHANUMERIC 0x0000000b +#define CTFMODEBIAS_HALFWIDTHALPHANUMERIC 0x0000000c + +#define EMO_EXIT 0x00000000 +#define EMO_ENTER 0x00000001 +#define EMO_PROMOTE 0x00000002 +#define EMO_EXPAND 0x00000003 +#define EMO_MOVESELECTION 0x00000004 +#define EMO_GETVIEWMODE 0x00000005 + +#define EMO_EXPANDSELECTION 0x00000000 +#define EMO_EXPANDDOCUMENT 0x00000001 + +/* Page Rotate values used in wParam of EM_SETPAGEROTATE message */ +#define EPR_0 0x00000000 +#define EPR_270 0x00000001 +#define EPR_180 0x00000002 +#define EPR_90 0x00000003 + +/* Find flags for wParam of EM_FINDTEXT message */ +#define FR_MATCHDIAC 0x20000000 +#define FR_MATCHKASHIDA 0x40000000 +#define FR_MATCHALEFHAMZA 0x80000000 + +/* IME Compatibility Mode return values for EM_GETIMECOMPMODE message */ +#define ICM_NOTOPEN 0x00000000 +#define ICM_LEVEL3 0x00000001 +#define ICM_LEVEL2 0x00000002 +#define ICM_LEVEL2_5 0x00000003 +#define ICM_LEVEL2_SUI 0x00000004 +#define ICM_CTF 0x00000005 + +/* Flags value for IMECOMPTEXT structure */ +#define ICT_RESULTREADSTR 0x00000001 + +/* Input Method Flags used in EM_SETLANGOPTIONS message */ +#define IMF_AUTOKEYBOARD 0x00000001 +#define IMF_AUTOFONT 0x00000002 +#define IMF_IMECANCELCOMPLETE 0x00000004 +#define IMF_IMEALWAYSSENDNOTIFY 0x00000008 +#define IMF_AUTOFONTSIZEADJUST 0x00000010 +#define IMF_UIFONTS 0x00000020 +#define IMF_DUALFONT 0x00000080 + +/* Parameters values for the EM_SETIMEMODEBIAS message */ +#define IMF_SMODE_PLAURALCLAUSE 0x00000001 +#define IMF_SMODE_NONE 0x00000002 /* Parameters of the EM_SETIMEOPTIONS message */ #define IMF_FORCENONE 0x00000001 @@ -566,6 +813,7 @@ typedef struct _gettextex { #define IMF_FORCEACTIVE 0x00000040 #define IMF_FORCEINACTIVE 0x00000080 #define IMF_FORCEREMEMBER 0x00000100 +#define IMF_MULTIPLEEDIT 0x00000400 /* return values of the EM_SELECTION_TYPE message */ #define SEL_EMPTY 0x00000000 @@ -574,6 +822,15 @@ typedef struct _gettextex { #define SEL_MULTICHAR 0x00000004 #define SEL_MULTIOBJECT 0x00000008 +/* ENOLEOPFAILED.lOper value that indicates operation failure */ +#define OLEOP_DOVERB 0x00000001 + +/* punctionation type values for wParam of EM_SETPUNCTUATION message */ +#define PC_FOLLOWING 0x00000001 +#define PC_LEADING 0x00000002 +#define PC_OVERFLOW 0x00000003 +#define PC_DELIMITER 0x00000004 + /* mask values in the PARAFORMAT structure */ #define PFM_STARTINDENT 0x00000001 #define PFM_RIGHTINDENT 0x00000002 @@ -590,7 +847,6 @@ typedef struct _gettextex { #define PFM_STYLE 0x00000400 #define PFM_BORDER 0x00000800 #define PFM_SHADING 0x00001000 - #define PFM_NUMBERINGSTYLE 0x00002000 #define PFM_NUMBERINGTAB 0x00004000 #define PFM_NUMBERINGSTART 0x00008000 @@ -602,10 +858,61 @@ typedef struct _gettextex { #define PFM_NOWIDOWCONTROL 0x00200000 #define PFM_DONOTHYPHEN 0x00400000 #define PFM_SIDEBYSIDE 0x00800000 +#define PFM_COLLAPSED 0x01000000 +#define PFM_OUTLINELEVEL 0x02000000 +#define PFM_BOX 0x04000000 +#define PFM_RESERVED2 0x08000000 +#define PFM_TABLEROWDELIMITER 0x10000000 +#define PFM_TEXTWRAPPINGBREAK 0x20000000 #define PFM_TABLE 0x40000000 +#define PFM_ALL (PFM_STARTINDENT | \ + PFM_RIGHTINDENT | \ + PFM_OFFSET | \ + PFM_ALIGNMENT | \ + PFM_TABSTOPS | \ + PFM_NUMBERING | \ + PFM_OFFSETINDENT | \ + PFM_RTLPARA) + +#define PFM_EFFECTS (PFM_RTLPARA | \ + PFM_KEEP | \ + PFM_KEEPNEXT | \ + PFM_PAGEBREAKBEFORE | \ + PFM_NOLINENUMBER | \ + PFM_NOWIDOWCONTROL | \ + PFM_DONOTHYPHEN | \ + PFM_SIDEBYSIDE | \ + PFM_TABLEROWDELIMITER | \ + PFM_TABLE) + +#define PFM_ALL2 (PFM_ALL | \ + PFM_EFFECTS | \ + PFM_SPACEBEFORE | \ + PFM_SPACEAFTER | \ + PFM_LINESPACING | \ + PFM_STYLE | \ + PFM_BORDER | \ + PFM_SHADING | \ + PFM_NUMBERINGSTYLE | \ + PFM_NUMBERINGTAB | \ + PFM_NUMBERINGSTART) + /* numbering option */ #define PFN_BULLET 0x00000001 +#define PFN_ARABIC 0x00000002 +#define PFN_LCLETTER 0x00000003 +#define PFN_UCLETTER 0x00000004 +#define PFN_LCROMAN 0x00000005 +#define PFN_UCROMAN 0x00000006 + +/* paragraph format numbering styles */ +#define PFNS_PAREN 0x00000000 +#define PFNS_PARENS 0x00000100 +#define PFNS_PERIOD 0x00000200 +#define PFNS_PLAIN 0x00000300 +#define PFNS_NONUMBER 0x00000400 +#define PFNS_NEWNUMBER 0x00008000 /* paragraph alignment */ #define PFA_LEFT 0x00000001 @@ -614,6 +921,9 @@ typedef struct _gettextex { #define PFA_JUSTIFY 0x00000004 #define PFA_FULL_INTERWORD 0x00000004 #define PFA_FULL_INTERLETTER 0x00000005 +#define PFA_FULL_SCALED 0x00000006 +#define PFA_FULL_GLYPHS 0x00000007 +#define PFA_SNAP_GRID 0x00000008 /* paragraph effects */ #define PFE_RTLPARA 0x00000001 @@ -624,17 +934,64 @@ typedef struct _gettextex { #define PFE_NOWIDOWCONTROL 0x00000020 #define PFE_DONOTHYPHEN 0x00000040 #define PFE_SIDEBYSIDE 0x00000080 +#define PFE_COLLAPSED 0x00000100 +#define PFE_BOX 0x00000400 +#define PFE_TABLEROWDELIMITER 0x00001000 +#define PFE_TEXTWRAPPINGBREAK 0x00002000 #define PFE_TABLE 0x00004000 +/* Set Edit Style flags for EM_SETEDITSTYLE message */ +#define SES_EMULATESYSEDIT 0x00000001 +#define SES_BEEPONMAXTEXT 0x00000002 +#define SES_EXTENDBACKCOLOR 0x00000004 +#define SES_MAPCPS 0x00000008 +#define SES_EMULATE10 0x00000010 +#define SES_USECRLF 0x00000020 +#define SES_NOXLTSYMBOLRANGE 0x00000020 +#define SES_USEAIMM 0x00000040 +#define SES_NOIME 0x00000080 +#define SES_ALLOWBEEPS 0x00000100 +#define SES_UPPERCASE 0x00000200 +#define SES_LOWERCASE 0x00000400 +#define SES_NOINPUTSEQUENCECHK 0x00000800 +#define SES_BIDI 0x00001000 +#define SES_SCROLLONKILLFOCUS 0x00002000 +#define SES_XLTCRCRLFTOCR 0x00004000 +#define SES_DRAFTMODE 0x00008000 +#define SES_USECTF 0x00010000 +#define SES_HIDEGRIDLINES 0x00020000 +#define SES_USEATFONT 0x00040000 +#define SES_CUSTOMLOOK 0x00080000 +#define SES_LBSCROLLNOTIFY 0x00100000 +#define SES_CTFALLOWEMBED 0x00200000 +#define SES_CTFALLOWSMARTTAG 0x00400000 +#define SES_CTFALLOWPROOFING 0x00800000 + /* streaming flags */ +#define SFF_WRITEXTRAPAR 0x00000080 #define SFF_PWD 0x00000800 #define SFF_KEEPDOCINFO 0x00001000 #define SFF_PERSISTVIEWSCALE 0x00002000 #define SFF_PLAINRTF 0x00004000 #define SFF_SELECTION 0x00008000 +typedef enum _undonameid +{ + UID_UNKNOWN = 0, + UID_TYPING = 1, + UID_DELETE = 2, + UID_DRAGDROP = 3, + UID_CUT = 4, + UID_PASTE = 5, + UID_AUTOCORRECT = 6 +} UNDONAMEID; + typedef LONG (*EDITWORDBREAKPROCEX)(char*,LONG,BYTE,INT); +#define VM_OUTLINE 0x00000002 +#define VM_NORMAL 0x00000004 +#define VM_PAGE 0x00000009 + /* options of the EM_FINDWORDBREAK message */ #define WB_CLASSIFY 0x00000003 #define WB_MOVEWORDLEFT 0x00000004 @@ -654,6 +1011,16 @@ typedef LONG (*EDITWORDBREAKPROCEX)(char*,LONG,BYTE,INT); #define WBF_LEVEL2 0x00000100 #define WBF_CUSTOM 0x00000200 +#define WBF_CLASS ((BYTE) 0x0F) +#define WBF_ISWHITE ((BYTE) 0x10) +#define WBF_BREAKLINE ((BYTE) 0x20) +#define WBF_BREAKAFTER ((BYTE) 0x40) + +/* Placeholder unicode character for an embedded object */ +#ifndef WCH_EMBEDDING +#define WCH_EMBEDDING (WCHAR)0xFFFC +#endif + /* options of the EM_SETTEXTMODE message */ #define TM_PLAINTEXT 0x00000001 #define TM_RICHTEXT 0x00000002 @@ -666,10 +1033,14 @@ typedef LONG (*EDITWORDBREAKPROCEX)(char*,LONG,BYTE,INT); #define GT_DEFAULT 0x00000000 #define GT_USECRLF 0x00000001 #define GT_SELECTION 0x00000002 +#define GT_RAWTEXT 0x00000004 +#define GT_NOHIDDENTEXT 0x00000008 /* Options of the EM_SETTYPOGRAPHYOPTIONS message */ -#define TO_ADVANCEDTYPOGRAPHY 0x00000001 -#define TO_SIMPLELINEBREAK 0x00000002 +#define TO_ADVANCEDTYPOGRAPHY 0x00000001 +#define TO_SIMPLELINEBREAK 0x00000002 +#define TO_DISABLECUSTOMTEXTOUT 0x00000004 +#define TO_ADVANCEDLAYOUT 0x00000008 typedef struct _gettextlengthex { DWORD flags; @@ -697,6 +1068,7 @@ typedef struct _settextex { #define ST_KEEPUNDO 0x00000001 #define ST_SELECTION 0x00000002 +#define ST_NEWCHARS 0x00000004 #ifdef __cplusplus } diff --git a/include/rpcdce.h b/include/rpcdce.h index 0212c4c3735..6bc656121d0 100644 --- a/include/rpcdce.h +++ b/include/rpcdce.h @@ -139,6 +139,11 @@ typedef I_RPC_HANDLE *RPC_EP_INQ_HANDLE; #define RPC_C_AUTHN_MQ 100 #define RPC_C_AUTHN_DEFAULT 0xffffffff +#define RPC_C_AUTHZ_NONE 0 +#define RPC_C_AUTHZ_NAME 1 +#define RPC_C_AUTHZ_DCE 2 +#define RPC_C_AUTHZ_DEFAULT 0xffffffff + /* values for RPC_SECURITY_QOS*::ImpersonationType */ #define RPC_C_IMP_LEVEL_DEFAULT 0 #define RPC_C_IMP_LEVEL_ANONYMOUS 1 diff --git a/include/rpcndr.h b/include/rpcndr.h index a0968d58ec2..9bf28407951 100644 --- a/include/rpcndr.h +++ b/include/rpcndr.h @@ -183,7 +183,7 @@ typedef struct _MIDL_STUB_MESSAGE struct NDR_POINTER_QUEUE_STATE *pPointerQueueState; int IgnoreEmbeddedPointers; unsigned char *PointerBufferMark; - unsigned char fBufferValid; + unsigned char CorrDespIncrement; unsigned char uFlags; unsigned short UniquePtrCount; ULONG_PTR MaxCount; @@ -205,7 +205,14 @@ typedef struct _MIDL_STUB_MESSAGE int fHasReturn:1; int fHasExtensions:1; int fHasNewCorrDesc:1; - int fUnused:10; + int fIsIn:1; + int fIsOut:1; + int fIsOicf:1; + int fBufferValid:1; + int fHasMemoryValidateCallback:1; + int fInFree:1; + int fNeedMCCP:1; + int fUnused:3; int fUnused2:16; DWORD dwDestContext; void *pvDestContext; diff --git a/include/shobjidl.idl b/include/shobjidl.idl index 563d9e2d459..31d211db0b8 100644 --- a/include/shobjidl.idl +++ b/include/shobjidl.idl @@ -1120,7 +1120,8 @@ interface IContextMenu3 : IContextMenu2 [ object, uuid(000214f5-0000-0000-c000-000000000046), - pointer_default(unique) + pointer_default(unique), + local ] interface IShellExecuteHookA : IUnknown { @@ -1136,7 +1137,8 @@ interface IShellExecuteHookA : IUnknown [ object, uuid(000214fb-0000-0000-c000-000000000046), - pointer_default(unique) + pointer_default(unique), + local ] interface IShellExecuteHookW : IUnknown { diff --git a/include/uuids.h b/include/uuids.h index 9f57dd724b8..344957f1bb1 100644 --- a/include/uuids.h +++ b/include/uuids.h @@ -273,5 +273,6 @@ OUR_GUID_ENTRY(CLSID_VideoProcAmpPropertyPage, 0x71f96464, 0x78f3, 0x11d0, OUR_GUID_ENTRY(CLSID_CameraControlPropertyPage, 0x71f96465, 0x78f3, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56) OUR_GUID_ENTRY(CLSID_AnalogVideoDecoderPropertyPage, 0x71f96466, 0x78f3, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56) OUR_GUID_ENTRY(CLSID_VideoStreamConfigPropertyPage, 0x71f96467, 0x78f3, 0x11d0, 0xa1, 0x8c, 0x00, 0xa0, 0xc9, 0x11, 0x89, 0x56) +OUR_GUID_ENTRY(CLSID_VideoMixingRenderer9, 0x51b4abf3, 0x748f, 0x4e3b, 0xa2, 0x76, 0xc8, 0x28, 0x33, 0x0e, 0x92, 0x6a) #undef OUR_GUID_ENTRY diff --git a/include/vmr9.idl b/include/vmr9.idl new file mode 100644 index 00000000000..e5e5fd8b6f7 --- /dev/null +++ b/include/vmr9.idl @@ -0,0 +1,525 @@ +/* + * Copyright 2008 Maarten Lankhorst + * + * 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 + */ + +import "unknwn.idl"; + +cpp_quote("#if 0") +interface IDirect3DSurface9; +interface IDirect3DDevice9; +typedef LONGLONG REFERENCE_TIME; +typedef DWORD D3DFORMAT; +typedef DWORD D3DPOOL; +typedef HANDLE HMONITOR; +typedef HANDLE HDC; +typedef struct { } AM_MEDIA_TYPE; +typedef struct { } D3DCOLOR; +cpp_quote("#endif") + +interface IVMRSurface9; +interface IVMRSurfaceAllocator9; +interface IVMRSurfaceAllocatorEx9; +interface IVMRSurfaceAllocatorNotify9; +interface IVMRImagePresenter9; +interface IVMRImagePresenterConfig9; +interface IVMRMonitorConfig9; +interface IVMRWindowlessControl9; +interface IVMRMixerControl9; +interface IVMRImageCompositor9; +interface IVMRMixerBitmap9; +interface IVMRFilterConfig9; +interface IVMRAspectRatioControl9; +interface IVMRVideoStreamControl9; + +typedef enum _VMR9PresentationFlags +{ + VMR9Sample_SyncPoint = 0x1, + VMR9Sample_Preroll = 0x2, + VMR9Sample_Discontinuity = 0x4, + VMR9Sample_TimeValid = 0x8, + VMR9Sample_SrcDstRectsValid = 0x10 +} VMR9PresentationFlags; + +typedef struct _VMR9PresentationInfo +{ + DWORD dwFlags; /* Flags defined above */ + IDirect3DSurface9 *lpSurf; + REFERENCE_TIME rtStart; + REFERENCE_TIME rtEnd; + SIZE szAspectRatio; + RECT rcSrc; + RECT rcDst; + DWORD dwReserved1; + DWORD dwReserved2; +} VMR9PresentationInfo; + +[ + local, + object, + uuid(69188c61-12a3-40f0-8ffc-342e7b433fd7), + helpstring("IVMRImagePresenter9 interface"), + pointer_default(unique) +] +interface IVMRImagePresenter9 : IUnknown +{ + HRESULT StartPresenting([in] DWORD_PTR id); + HRESULT StopPresenting([in] DWORD_PTR id); + HRESULT PresentImage([in] DWORD_PTR id, [in] VMR9PresentationInfo *info); +}; + +typedef enum _VMR9SurfaceAllocationFlags +{ + VMR9AllocFlag_3DRenderTarget = 0x1, + VMR9AllocFlag_DXVATarget = 0x2, + VMR9AllocFlag_TextureSurface = 0x4, + VMR9AllocFlag_OffscreenSurface = 0x8, + VMR9AllocFlag_RGBDynamicSwitch = 0x10, + VMR9AllocFlag_UsageReserved = 0xe0, + VMR9AllocFlag_UsageMask = 0xff, +} VMR9SurfaceAllocationFlags; + +typedef struct _VMR9AllocationInfo +{ + DWORD dwFlags; /* Flags defined above */ + DWORD dwWidth; + DWORD dwHeight; + D3DFORMAT Format; + D3DPOOL Pool; + DWORD MinBuffers; + SIZE szAspectRatio; + SIZE szNativeSize; +} VMR9AllocationInfo; + +[ + local, + object, + uuid(8d5148ea-3f5d-46cf-9df1-d1b896eedb1f), + helpstring("IVMRSurfaceAllocator9 interface"), + pointer_default(unique) +] +interface IVMRSurfaceAllocator9 : IUnknown +{ + HRESULT InitializeDevice([in] DWORD_PTR id, [in] VMR9AllocationInfo *allocinfo, [in, out] DWORD *numbuffers); + HRESULT TerminateDevice([in] DWORD_PTR id); + HRESULT GetSurface([in] DWORD_PTR id, [in] DWORD surfaceindex, [in] DWORD flags, [out] IDirect3DSurface9 **surface); + HRESULT AdviseNotify([in] IVMRSurfaceAllocatorNotify9 *allocnotify); +}; + +[ + local, + object, + uuid(6de9a68a-a928-4522-bf57-655ae3866456), + helpstring("IVMRSurfaceAllocatorEx9 interface"), + pointer_default(unique) +] +interface IVMRSurfaceAllocatorEx9 : IVMRSurfaceAllocator9 +{ + HRESULT GetSurfaceEx([in] DWORD_PTR id, [in] DWORD surfaceindex, [in] DWORD flags, [out] IDirect3DSurface9 **surface, [out] RECT *dest); +}; + +[ + local, + object, + uuid(dca3f5df-bb3a-4d03-bd81-84614bfbfa0c), + helpstring("IVMRSurfaceAllocatorNotify9 interface"), + pointer_default(unique) +] +interface IVMRSurfaceAllocatorNotify9 : IUnknown +{ + HRESULT AdviseSurfaceAllocator([in] DWORD_PTR id, [in] IVMRSurfaceAllocator9 *alloc); + HRESULT SetD3DDevice([in] IDirect3DDevice9 *device, [in] HMONITOR monitor); + HRESULT ChangeD3DDevice([in] IDirect3DDevice9 *device, [in] HMONITOR monitor); + HRESULT AllocateSurfaceHelper([in] VMR9AllocationInfo *allocinfo, [in, out] DWORD *numbuffers, [out] IDirect3DSurface9 **surface); + HRESULT NotifyEvent([in] LONG code, [in] LONG_PTR param1, [in] LONG_PTR param2); +}; + +typedef enum _VMR9AspectRatioMode +{ + VMR9ARMode_None, + VMR9ARMode_LetterBox +} VMR9AspectRatioMode; + +[ + local, + object, + uuid(8f537d09-f85e-4414-b23b-502e54c79927), + helpstring("IVMRWindowlessControl interface"), + pointer_default(unique) +] +interface IVMRWindowlessControl9 : IUnknown +{ + HRESULT GetNativeVideoSize([out] LONG *width, [out] LONG *height, [out] LONG *arwidth, [out] LONG *arheight); + HRESULT GetMinIdealVideoSize([out] LONG *width, [out] LONG *height); + HRESULT GetMaxIdealVideoSize([out] LONG *width, [out] LONG *height); + HRESULT SetVideoPosition([in] const RECT *source, [in] const RECT *dest); + HRESULT GetVideoPosition([out] RECT *source, [out] RECT *dest); + HRESULT GetAspectRatioMode([out] DWORD *mode); + HRESULT SetAspectRatioMode([in] DWORD mode); + HRESULT SetVideoClippingWindow([in] HWND hwnd); + HRESULT RepaintVideo([in] HWND hwnd, [in] HDC hdc); + HRESULT DisplayModeChanged(); + HRESULT GetCurrentImage([out] BYTE **dib); + HRESULT SetBorderColor([in] COLORREF color); + HRESULT GetBorderColor([out] COLORREF *color); +}; + +typedef enum _VMR9MixerPrefs +{ + /* Decimation */ + MixerPref9_NoDecimation = 0x1, + MixerPref9_DecimateOutput = 0x2, + MixerPref9_ARAdjustXorY = 0x4, + MixerPref9_NonSquareMixing = 0x8, + MixerPref9_DecimateMask = 0xf, + + /* Filtering */ + MixerPref9_BiLinearFiltering = 0x10, + MixerPref9_PointFiltering = 0x20, + MixerPref9_AnisotropicFiltering = 0x40, + MixerPref9_PyramidalQuadFiltering = 0x80, + MixerPref9_GaussianQuadFiltering = 0x100, + MixerPref9_FilteringReserved = 0xe00, + MixerPref9_FilteringMask = 0xff0, + + /* Render target */ + MixerPref9_RenderTargetRGB = 0x1000, + MixerPref9_RenderTargetYUV = 0x2000, + MixerPref9_RenderTargetReserved = 0xfc000, + + MixerPref9_DynamicSwitchToBOB = 0x100000, + MixerPref9_DynamicDecimateBy2 = 0x200000, + MixerPref9_DynamicReserved = 0xc00000, + MixerPref9_DynamicMask = 0xf00000, +} VMR9MixerPrefs; + +typedef struct _VMR9NormalizedRect +{ + FLOAT left; + FLOAT top; + FLOAT right; + FLOAT bottom; +} VMR9NormalizedRect; + +typedef enum _VMR9ProcAmpControlFlags +{ + ProcAmpControl9_Brightness = 0x1, + ProcAmpControl9_Contrast = 0x2, + ProcAmpControl9_Hue = 0x4, + ProcAmpControl9_Saturation = 0x8, + ProcAmpControl9_Mask = 0xf +} VMR9ProcAmpControlFlags; + +typedef struct _VMR9ProcAmpControl +{ + DWORD dwSize; + DWORD dwFlags; + FLOAT Brightness; + FLOAT Contrast; + FLOAT Hue; + FLOAT Saturation; +} VMR9ProcAmpControl; + +typedef struct _VMR9ProcAmpControlRange +{ + DWORD dwSize; + VMR9ProcAmpControlFlags dwProperty; + FLOAT MinValue; + FLOAT MaxValue; + FLOAT DefaultValue; + FLOAT StepSize; +} VMR9ProcAmpControlRange; + +[ + local, + object, + uuid(1a777eaa-47c8-4930-b2c9-8fee1c1b0f3b), + helpstring("IVMRMixerControl9 interface"), + pointer_default(unique) +] +interface IVMRMixerControl9 : IUnknown +{ + HRESULT SetAlpha([in] DWORD streamid, [in] FLOAT alpha); + HRESULT GetAlpha([in] DWORD streamid, [out] FLOAT *alpha); + HRESULT SetZOrder([in] DWORD streamid, [in] DWORD zorder); + HRESULT GetZOrder([in] DWORD streamid, [out] DWORD *zorder); + HRESULT SetOutputRect([in] DWORD streamid, [in] const VMR9NormalizedRect *rect); + HRESULT GetOutputRect([in] DWORD streamid, [out] VMR9NormalizedRect *rect); + HRESULT SetBackgroundClr([in] COLORREF back); + HRESULT GetBackgroundClr([out] COLORREF *back); + HRESULT SetMixingPrefs([in] DWORD mixingprefs); + HRESULT GetMixingPrefs([out] DWORD *mixingprefs); + HRESULT SetProcAmpControl([in] DWORD streamid, [in] VMR9ProcAmpControl *control); + HRESULT GetProcAmpControl([in] DWORD streamid, [in, out] VMR9ProcAmpControl *control); + HRESULT GetProcAmpControlRange([in] DWORD streamid, [in, out] VMR9ProcAmpControlRange *controlrange); +}; + +typedef struct _VMR9AlphaBitmap +{ + DWORD dwFlags; + HDC hdc; + IDirect3DSurface9 *pDDS; + RECT rSrc; + VMR9NormalizedRect *rDest; + FLOAT fAlpha; + COLORREF clrSrcKey; + DWORD dwFilterMode; +} VMR9AlphaBitmap; + +typedef enum _VMR9AlphaBitmapFlags +{ + VMR9AlphaBitmap_Disable = 0x1, + VMR9AlphaBitmap_hDC = 0x2, + VMR9AlphaBitmap_EntireDDS = 0x4, + VMR9AlphaBitmap_SrcColorKey = 0x8, + VMR9AlphaBitmap_SrcRect = 0x10, + VMR9AlphaBitmap_FilterMode = 0x20 +} VMR9AlphaBitmapFlags; + +[ + local, + object, + uuid(ced175e5-1935-4820-81bd-ff6ad00c9108), + helpstring("IVMRMixerBitmap interface"), + pointer_default(unique) +] +interface IVMRMixerBitmap9 : IUnknown +{ + HRESULT SetAlphaBitmap([in] const VMR9AlphaBitmap *bitmap); + HRESULT UpdateAlphaBitmapParameters([in] const VMR9AlphaBitmap *bitmap); + HRESULT GetAlphaBitmapParameters([out] VMR9AlphaBitmap *bitmap); +}; + +[ + local, + object, + uuid(dfc581a1-6e1f-4c3a-8d0a-5e9792ea2afc), + helpstring("IVMRSurface interface"), + pointer_default(unique) +] +interface IVMRSurface9 : IUnknown +{ + HRESULT IsSurfaceLocked(); + HRESULT LockSurface([out] BYTE **surface); + HRESULT UnlockSurface(); + HRESULT GetSurface([out] IDirect3DSurface9 **surface); +}; + +typedef enum _VMR9RenderPrefs +{ + RenderPrefs9_DoNotRenderBorder = 0x1, + RenderPrefs9_Mask = 0x1 +} VMR9RenderPrefs; + +[ + local, + object, + uuid(45c15cab-6e22-420a-8043-ae1f0ac02c7d), + helpstring("IVMRImagePresenterConfig9 interface"), + pointer_default(unique) +] +interface IVMRImagePresenterConfig9 : IUnknown +{ + HRESULT SetRenderingPrefs([in] DWORD renderflags); + HRESULT GetRenderingPrefs([out] DWORD *renderflags); +}; + +[ + local, + object, + uuid(d0cfe38b-93e7-4772-8957-0400c49a4485), + helpstring("IVMRMixerStreamConfig interface"), + pointer_default(unique) +] +interface IVMRVideoStreamControl9: IUnknown +{ + HRESULT SetStreamActiveState([in] BOOL active); + HRESULT GetStreamActiveState([out] BOOL *active); +}; + +typedef enum _VMR9Mode +{ + VMR9Mode_Windowed = 0x1, + VMR9Mode_Windowless = 0x2, + VMR9Mode_Renderless = 0x4, + VMR9Mode_Mask = 0x7 +} VMR9Mode; + +[ + local, + object, + uuid(5a804648-4f66-4867-9c43-4f5c822cf1b8), + helpstring("IVMRFilterConfig9 interface"), + pointer_default(unique) +] +interface IVMRFilterConfig9 : IUnknown +{ + HRESULT SetImageCompositor([in] IVMRImageCompositor9 *compositor); + HRESULT SetNumberOfStreams([in] DWORD max); + HRESULT GetNumberOfStreams([out] DWORD *max); + HRESULT SetRenderingPrefs([in] DWORD renderflags); + HRESULT GetRenderingPrefs([out] DWORD *renderflags); + HRESULT SetRenderingMode([in] DWORD mode); + HRESULT GetRenderingMode([out] DWORD *mode); +}; + +[ + local, + object, + uuid(00d96c29-bbde-4efc-9901-bb5036392146), + helpstring("IVMRAspectRatioControl9 interface"), + pointer_default(unique) +] +interface IVMRAspectRatioControl9 : IUnknown +{ + HRESULT GetAspectRatioMode([out] DWORD *mode); + HRESULT SetAspectRatioMode([in] DWORD mode); +} + +#define VMR9DEVICENAMELEN 32 +#define VMR9DEVICEDESCRIPTIONLEN 512 + +typedef struct _VMR9MonitorInfo +{ + UINT uDevID; + RECT rcMonitor; + HMONITOR hMon; + DWORD dwFlags; + WCHAR szDevice[VMR9DEVICENAMELEN]; + WCHAR szDescription[VMR9DEVICEDESCRIPTIONLEN]; + LARGE_INTEGER liDriverVersion; + DWORD dwVendorId; + DWORD dwDeviceId; + DWORD dwSubSysId; + DWORD dwRevision; +} VMR9MonitorInfo; + +[ + local, + object, + uuid(46c2e457-8ba0-4eef-b80b-0680f0978749), + helpstring("IVMRMonitorConfig9 interface"), + pointer_default(unique) +] +interface IVMRMonitorConfig9 : IUnknown +{ + HRESULT SetMonitor([in] UINT uDev); + HRESULT GetMonitor([out] UINT *uDev); + HRESULT SetDefaultMonitor([in] UINT uDev); + HRESULT GetDefaultMonitor([out] UINT *uDev); + HRESULT GetAvailableMonitors([out, size_is(arraysize)] VMR9MonitorInfo *info, [in] DWORD arraysize, [out] DWORD *numdev); +}; + +typedef enum _VMR9DeinterlacePrefs +{ + DeinterlacePref9_NextBest = 0x1, + DeinterlacePref9_BOB = 0x2, + DeinterlacePref9_Weave = 0x4, + DeinterlacePref9_Mask = 0x7 +} VMR9DeinterlacePrefs; + +typedef enum _VMR9DeinterlaceTech +{ + DeinterlaceTech9_Unknown = 0, + DeinterlaceTech9_BOBLineReplicate = 0x1, + DeinterlaceTech9_BOBVerticalStretch = 0x2, + DeinterlaceTech9_MedianFiltering = 0x4, + DeinterlaceTech9_EdgeFiltering = 0x10, + DeinterlaceTech9_FieldAdaptive = 0x20, + DeinterlaceTech9_PixelAdaptive = 0x40, + DeinterlaceTech9_MotionVectorSteered = 0x80 +} VMR9DeinterlaceTech; + +typedef struct _VMR9Frequency +{ + DWORD dwNumerator; + DWORD dwDenominator; +} VMR9Frequency; + +typedef enum _VMR9_SampleFormat +{ + VMR9_SampleReserved = 1, + VMR9_SampleProgressiveFrame = 2, + VMR9_SampleFieldInterleavedEvenFirst = 3, + VMR9_SampleFieldInterleavedOddFirst = 4, + VMR9_SampleFieldSingleEven = 5, + VMR9_SampleFieldSingleOdd = 6, +} VMR9_SampleFormat; + +typedef struct _VMR9VideoDesc +{ + DWORD dwSize; + DWORD dwSampleWidth; + DWORD dwSampleHeight; + VMR9_SampleFormat SampleFormat; + DWORD dwFourCC; + VMR9Frequency InputSampleFreq; + VMR9Frequency OutputFrameFreq; +} VMR9VideoDesc; + +typedef struct _VMR9DeinterlaceCaps { + DWORD dwSize; + DWORD dwNumPreviousOutputFrames; + DWORD dwNumForwardRefSamples; + DWORD dwNumBackwardRefSamples; + VMR9DeinterlaceTech DeinterlaceTechnology; +} VMR9DeinterlaceCaps; + +[ + local, + object, + uuid(a215fb8d-13c2-4f7f-993c-003d6271a459), + helpstring("IVMRDeinterlaceControl9 interface"), + pointer_default(unique) +] +interface IVMRDeinterlaceControl9 : IUnknown +{ + HRESULT GetNumberOfDeinterlaceModes([in] VMR9VideoDesc *desc, [in, out] DWORD *nummodes, [out] GUID *modes); + HRESULT GetDeinterlaceModeCaps([in] GUID *mode, [in] VMR9VideoDesc *desc, [out] VMR9DeinterlaceCaps *caps); + HRESULT GetDeinterlaceMode([in] DWORD streamid, [out] GUID *mode); + HRESULT SetDeinterlaceMode([in] DWORD streamid, [in] GUID *mode); + HRESULT GetDeinterlacePrefs([out] DWORD *prefs); + HRESULT SetDeinterlacePrefs([in] DWORD prefs); + HRESULT GetActualDeinterlaceMode([in] DWORD streamid, [out] GUID *mode); +}; + +typedef struct _VMR9VideoStreamInfo { + IDirect3DSurface9 *pddsVideoSurface; + DWORD dwWidth; + DWORD dwHeight; + DWORD dwStrmID; + FLOAT fAlpha; + VMR9NormalizedRect rNormal; + REFERENCE_TIME rtStart; + REFERENCE_TIME rtEnd; + VMR9_SampleFormat SampleFormat; +} VMR9VideoStreamInfo; + +[ + local, + object, + uuid(4a5c89eb-df51-4654-ac2a-e48e02bbabf6), + helpstring("IVMRImageCompositor9 interface"), + pointer_default(unique) +] +interface IVMRImageCompositor9 : IUnknown +{ + HRESULT InitCompositionDevice([in] IUnknown *d3ddev); + HRESULT TermCompositionDevice([in] IUnknown *d3ddev); + HRESULT CompositeImage([in] IUnknown *d3ddev, [in] IDirect3DSurface9 *d3dtarget, [in] AM_MEDIA_TYPE *mttarget, + [in] REFERENCE_TIME start, [in] REFERENCE_TIME stop, D3DCOLOR back, + [in] VMR9VideoStreamInfo *info, [in] UINT streams); +}; diff --git a/include/winbase.h b/include/winbase.h index 433b98510d6..c47a1a500fe 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -54,6 +54,8 @@ typedef RTL_CRITICAL_SECTION_DEBUG CRITICAL_SECTION_DEBUG; typedef PRTL_CRITICAL_SECTION_DEBUG PCRITICAL_SECTION_DEBUG; typedef PRTL_CRITICAL_SECTION_DEBUG LPCRITICAL_SECTION_DEBUG; +#define CRITICAL_SECTION_NO_DEBUG_INFO RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO + typedef WAITORTIMERCALLBACKFUNC WAITORTIMERCALLBACK; #define EXCEPTION_DEBUG_EVENT 1 @@ -1777,6 +1779,7 @@ WINBASEAPI BOOL WINAPI InitAtomTable(DWORD); WINADVAPI BOOL WINAPI InitializeAcl(PACL,DWORD,DWORD); WINBASEAPI void WINAPI InitializeCriticalSection(CRITICAL_SECTION *lpCrit); WINBASEAPI BOOL WINAPI InitializeCriticalSectionAndSpinCount(CRITICAL_SECTION *,DWORD); +WINBASEAPI BOOL WINAPI InitializeCriticalSectionEx(CRITICAL_SECTION *,DWORD,DWORD); WINADVAPI BOOL WINAPI InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR,DWORD); WINADVAPI BOOL WINAPI InitializeSid(PSID,PSID_IDENTIFIER_AUTHORITY,BYTE); WINBASEAPI VOID WINAPI InitializeSListHead(PSLIST_HEADER); diff --git a/include/wine/dcetypes.idl b/include/wine/dcetypes.idl new file mode 100644 index 00000000000..8bfbb09e386 --- /dev/null +++ b/include/wine/dcetypes.idl @@ -0,0 +1,88 @@ +/* + * Common DCE Types + * + * Copyright 2006 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 + */ + +/* pull in GUID type */ +import "wtypes.idl"; + +typedef unsigned small unsigned8; +typedef unsigned short unsigned16; +typedef unsigned long unsigned32; +typedef small signed8; +typedef short signed16; +typedef long signed32; +typedef unsigned32 boolean32; +typedef unsigned hyper u_int64; +typedef unsigned long u_int32; +typedef unsigned short u_int16; +typedef unsigned small u_int8; + +typedef [ptr] GUID *uuid_p_t; + +typedef struct twr_t +{ + unsigned32 tower_length; + [size_is(tower_length)] byte tower_octet_string[]; +} twr_t; +typedef [ptr] twr_t *twr_p_t; + +typedef struct ndr_context_handle +{ + unsigned32 context_handle_attributes; + GUID context_handle_uuid; +} ndr_context_handle; + +const long ndr_c_int_big_endian = 0; +const long ndr_c_int_little_endian = 1; +const long ndr_c_float_ieee = 0; +const long ndr_c_float_vax = 1; +const long ndr_c_float_cray = 2; +const long ndr_c_float_ibm = 3; +const long ndr_c_char_ascii = 0; +const long ndr_c_char_ebcdic = 1; + +typedef struct +{ + unsigned8 int_rep; + unsigned8 char_rep; + unsigned8 float_rep; + byte reserved; +} ndr_format_t, *ndr_format_p_t; + +typedef struct +{ + GUID uuid; + unsigned16 vers_major; + unsigned16 vers_minor; +} rpc_if_id_t; +typedef [unique] rpc_if_id_t *rpc_if_id_p_t; + +typedef struct +{ + unsigned32 count; + [size_is(count)] + rpc_if_id_p_t if_id[*]; +} rpc_if_id_vector_t; +typedef [unique] rpc_if_id_vector_t *rpc_if_id_vector_p_t; + +typedef struct +{ + unsigned32 count; + unsigned32 stats[1]; /* length_is (count) */ +} rpc_stats_vector_t, *rpc_stats_vector_p_t; diff --git a/include/wine/epm.idl b/include/wine/epm.idl new file mode 100644 index 00000000000..301deb6810a --- /dev/null +++ b/include/wine/epm.idl @@ -0,0 +1,122 @@ +/* + * Endpoint Mapper + * + * Copyright 2006 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 + */ + +/* FIXME: should be import */ +#include "dcetypes.idl" + +cpp_quote("RPC_STATUS WINAPI TowerExplode(") +cpp_quote(" const twr_t *tower, PRPC_SYNTAX_IDENTIFIER object, PRPC_SYNTAX_IDENTIFIER syntax,") +cpp_quote(" char **protseq, char **endpoint, char **address);") +cpp_quote("RPC_STATUS WINAPI TowerConstruct(") +cpp_quote(" const RPC_SYNTAX_IDENTIFIER *object, const RPC_SYNTAX_IDENTIFIER *syntax,") +cpp_quote(" const char *protseq, const char *endpoint, const char *address,") +cpp_quote(" twr_t **tower);") + +[ + uuid(e1af8308-5d1f-11c9-91a4-08002b14a0fa), + version(3.0), + pointer_default(ref) +] +interface epm +{ + const long ept_max_annotation_size = 64; + + typedef struct + { + GUID object; + twr_t *tower; + [string] char annotation[ept_max_annotation_size]; + } ept_entry_t, *ept_entry_p_t; + + typedef [context_handle] void *ept_lookup_handle_t; + + /* Adds entries to an endpoint map */ + void ept_insert( + [in] handle_t h, + [in] unsigned32 num_ents, + [in, size_is(num_ents)] + ept_entry_t entries[], + [in] boolean32 replace, + [out] error_status_t *status + ); + + /* Removes entries from an endpoint map */ + void ept_delete( + [in] handle_t h, + [in] unsigned32 num_ents, + [in, size_is(num_ents)] + ept_entry_t entries[], + [out] error_status_t *status + ); + + /* Lookup entries in an endpoint map */ + [idempotent] + void ept_lookup( + [in] handle_t h, + [in] unsigned32 inquiry_type, + [in] uuid_p_t object, + [in] rpc_if_id_p_t interface_id, + [in] unsigned32 vers_option, + [in, out] ept_lookup_handle_t *entry_handle, + [in] unsigned32 max_ents, + [out] unsigned32 *num_ents, + [out, length_is(*num_ents), size_is(max_ents)] + ept_entry_t entries[], + [out] error_status_t *status + ); + + /* Lookup entries in an endpoint map using the given input pattern */ + [idempotent] + void ept_map( + [in] handle_t h, + [in] uuid_p_t object, + [in] twr_p_t map_tower, + [in, out] ept_lookup_handle_t *entry_handle, + [in] unsigned32 max_towers, + [out] unsigned32 *num_towers, + [out, length_is(*num_towers), size_is(max_towers)] + twr_p_t *towers, + [out] error_status_t *status + ); + + /* Free the context handle returned by ept_lookup or ept_map */ + void ept_lookup_handle_free( + [in] handle_t h, + [in, out] ept_lookup_handle_t *entry_handle, + [out] error_status_t *status + ); + + /* Inquires as to the endpoint map's object identifier */ + [idempotent] + void ept_inq_object( + [in] handle_t h, + [out] GUID *ept_object, + [out] error_status_t *status + ); + + /* Deletes matching entries in the endpoint map */ + void ept_mgmt_delete( + [in] handle_t h, + [in] boolean32 object_speced, + [in] uuid_p_t object, + [in] twr_p_t tower, + [out] error_status_t *status + ); +} diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 80843316a36..fadbf3a0c88 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2880,7 +2880,8 @@ struct get_desktop_window_request struct get_desktop_window_reply { struct reply_header __header; - user_handle_t handle; + user_handle_t top_window; + user_handle_t msg_window; }; @@ -5095,6 +5096,6 @@ union generic_reply struct add_fd_completion_reply add_fd_completion_reply; }; -#define SERVER_PROTOCOL_VERSION 339 +#define SERVER_PROTOCOL_VERSION 340 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/include/wine/wined3d_types.h b/include/wine/wined3d_types.h index d85e343e11d..45a947d0da4 100644 --- a/include/wine/wined3d_types.h +++ b/include/wine/wined3d_types.h @@ -1334,7 +1334,7 @@ typedef enum { #define WINED3DUSAGE_AUTOGENMIPMAP 0x00000400L #define WINED3DUSAGE_DMAP 0x00004000L #define WINED3DUSAGE_MASK 0x00004FFFL -#define WINED3DUSAGE_OVERLAY 0x00010000L +#define WINED3DUSAGE_OVERLAY 0x80000000L #define WINED3DUSAGE_QUERY_LEGACYBUMPMAP 0x00008000L #define WINED3DUSAGE_QUERY_FILTER 0x00020000L @@ -1343,7 +1343,7 @@ typedef enum { #define WINED3DUSAGE_QUERY_SRGBWRITE 0x00040000L #define WINED3DUSAGE_QUERY_VERTEXTEXTURE 0x00100000L #define WINED3DUSAGE_QUERY_WRAPANDMIP 0x00200000L -#define WINED3DUSAGE_QUERY_MASK 0x002F8000L +#define WINED3DUSAGE_QUERY_MASK 0x003F8000L typedef enum _WINED3DSURFTYPE { SURFACE_UNKNOWN = 0, /* Default / Unknown surface type */ diff --git a/include/winnt.h b/include/winnt.h index 70853638855..f9ae9d4a4a5 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -4700,6 +4700,12 @@ typedef struct _RTL_CRITICAL_SECTION { ULONG_PTR SpinCount; } RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION; +#define RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO 0x1000000 +#define RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN 0x2000000 +#define RTL_CRITICAL_SECTION_FLAG_STATIC_INIT 0x4000000 +#define RTL_CRITICAL_SECTION_ALL_FLAG_BITS 0xFF000000 +#define RTL_CRITICAL_SECTION_FLAG_RESERVED (RTL_CRITICAL_SECTION_ALL_FLAG_BITS & ~0x7000000) + typedef VOID (NTAPI * WAITORTIMERCALLBACKFUNC) (PVOID, BOOLEAN ); typedef VOID (NTAPI * PFLS_CALLBACK_FUNCTION) ( PVOID ); diff --git a/include/winternl.h b/include/winternl.h index 39339c2b77a..fe2f83d3feb 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2219,7 +2219,8 @@ NTSYSAPI NTSTATUS WINAPI RtlInitAnsiStringEx(PANSI_STRING,PCSZ); NTSYSAPI void WINAPI RtlInitUnicodeString(PUNICODE_STRING,PCWSTR); NTSYSAPI NTSTATUS WINAPI RtlInitUnicodeStringEx(PUNICODE_STRING,PCWSTR); NTSYSAPI NTSTATUS WINAPI RtlInitializeCriticalSection(RTL_CRITICAL_SECTION *); -NTSYSAPI NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount(RTL_CRITICAL_SECTION *,DWORD); +NTSYSAPI NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount(RTL_CRITICAL_SECTION *,ULONG); +NTSYSAPI NTSTATUS WINAPI RtlInitializeCriticalSectionEx(RTL_CRITICAL_SECTION *,ULONG,ULONG); NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP,PULONG,ULONG); NTSYSAPI void WINAPI RtlInitializeHandleTable(ULONG,ULONG,RTL_HANDLE_TABLE *); NTSYSAPI void WINAPI RtlInitializeResource(LPRTL_RWLOCK); diff --git a/include/xmldom.idl b/include/xmldom.idl index 1aac0ba5156..bf85acfb7f0 100644 --- a/include/xmldom.idl +++ b/include/xmldom.idl @@ -591,6 +591,7 @@ interface IXMLDOMCDATASection : IXMLDOMText { /* empty */ } + [ local, object, @@ -618,6 +619,77 @@ local, object, odl, dual, +nonextensible, +oleautomation, +uuid(2933bf8c-7b36-11d2-b20e-00c04f983e60), +pointer_default(unique) +] +interface IXMLDOMNotation : IXMLDOMNode +{ + [propget, id(DISPID_DOM_NOTATION_PUBLICID)] + HRESULT publicId([out, retval] VARIANT *publicId); + + [propget, id(DISPID_DOM_NOTATION_SYSTEMID)] + HRESULT systemId([out, retval] VARIANT *systemId); +} + +[ +local, +object, +odl, +dual, +nonextensible, +oleautomation, +uuid(2933bf8d-7b36-11d2-b20e-00c04f983e60), +pointer_default(unique) +] +interface IXMLDOMEntity : IXMLDOMNode +{ + [propget, id(DISPID_DOM_ENTITY_PUBLICID)] + HRESULT publicId([out, retval] VARIANT *publicId); + + [propget, id(DISPID_DOM_ENTITY_SYSTEMID)] + HRESULT systemId([out, retval] VARIANT *systemId); + + [propget, id(DISPID_DOM_ENTITY_NOTATIONNAME)] + HRESULT notationName([out, retval] BSTR *name); +} + +[ +local, +object, +odl, +dual, +nonextensible, +oleautomation, +uuid(2933bf8e-7b36-11d2-b20e-00c04f983e60), +pointer_default(unique) +] +interface IXMLDOMEntityReference : IXMLDOMNode +{ +} + +[ +local, +object, +odl, +dual, +nonextensible, +oleautomation, +uuid(2933bf8f-7b36-11d2-b20e-00c04f983e60), +pointer_default(unique) +] +interface IXMLDOMImplementation : IDispatch +{ + [id(DISPID_DOM_IMPLEMENTATION_HASFEATURE)] + HRESULT hasFeature([in] BSTR feature, [in] BSTR version, [out, retval] VARIANT_BOOL *pbool); +} + +[ +local, +object, +odl, +dual, oleautomation, /*nonextensible,*/ helpstring("structure for reporting parse errors"), diff --git a/include/xmldomdid.h b/include/xmldomdid.h index 4e8dc855722..a299157c3ac 100644 --- a/include/xmldomdid.h +++ b/include/xmldomdid.h @@ -171,6 +171,21 @@ #define DISPID_DOM_DOCUMENTTYPE_NOTATIONS 131 #define DISPID_DOM_DOCUMENTTYPE__TOP 132 +#define DISPID_DOM_NOTATION 133 +#define DISPID_DOM_NOTATION_PUBLICID 134 +#define DISPID_DOM_NOTATION_SYSTEMID 135 +#define DISPID_DOM_NOTATION__TOP 136 + +#define DISPID_DOM_ENTITY 137 +#define DISPID_DOM_ENTITY_PUBLICID 138 +#define DISPID_DOM_ENTITY_SYSTEMID 139 +#define DISPID_DOM_ENTITY_NOTATIONNAME 140 +#define DISPID_DOM_ENTITY__TOP 141 + +#define DISPID_DOM_IMPLEMENTATION 142 +#define DISPID_DOM_IMPLEMENTATION_HASFEATURE 143 +#define DISPID_DOM_IMPLEMENTATION__TOP 144 + #define DISPID_DOM_ERROR 0x000000b0 #define DISPID_DOM_ERROR_ERRORCODE 0x000000b1 diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c index 246e14b7b92..552d11bab6c 100644 --- a/programs/explorer/desktop.c +++ b/programs/explorer/desktop.c @@ -230,8 +230,9 @@ static void set_desktop_window_title( HWND hwnd, const WCHAR *name ) void manage_desktop( WCHAR *arg ) { static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',0}; + static const WCHAR messageW[] = {'M','e','s','s','a','g','e',0}; MSG msg; - HWND hwnd; + HWND hwnd, msg_hwnd; unsigned long xwin = 0; unsigned int width, height; WCHAR *cmdline = NULL; @@ -293,6 +294,11 @@ void manage_desktop( WCHAR *arg ) GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN), GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN), 0, 0, 0, NULL ); + + /* create the HWND_MESSAGE parent */ + msg_hwnd = CreateWindowExW( 0, messageW, NULL, WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + 0, 0, 100, 100, 0, 0, 0, NULL ); + if (hwnd == GetDesktopWindow()) { SetWindowLongPtrW( hwnd, GWLP_WNDPROC, (LONG_PTR)desktop_wnd_proc ); @@ -309,6 +315,8 @@ void manage_desktop( WCHAR *arg ) hwnd = 0; } + if (GetAncestor( msg_hwnd, GA_PARENT )) DestroyWindow( msg_hwnd ); /* someone beat us to it */ + /* if we have a command line, execute it */ if (cmdline) { diff --git a/programs/oleview/Ru.rc b/programs/oleview/Ru.rc new file mode 100644 index 00000000000..29aca2a59cb --- /dev/null +++ b/programs/oleview/Ru.rc @@ -0,0 +1,213 @@ +/* + * OleView (Ru.rc) + * Russian Language Support + * + * Copyright 2008 Vladimir Pankratov + * + * 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 + */ + +LANGUAGE LANG_RUSSIAN, SUBLANG_RUSSIAN + +IDM_MENU MENU +{ + POPUP "&Ôàéë" + { + MENUITEM "Ï&ðèâÿçàòü ê ôàéëó...", IDM_BIND + MENUITEM "&Ïðîñìîòð TypeLib...", IDM_TYPELIB + MENUITEM SEPARATOR + MENUITEM "&Êîíôèãóðàöèÿ ñèñòåìû...", IDM_SYSCONF + MENUITEM "&Çàïóñòèòü Ðåäàêòîð ðååñòðà", IDM_REGEDIT + MENUITEM SEPARATOR + MENUITEM "&Âûõîä", IDM_EXIT + } + POPUP "&Îáüåêò" + { + POPUP "&CoCreateInstance Flag" + { + MENUITEM "CLSCTX_&INPROC_SERVER", IDM_FLAG_INSERV,CHECKED + MENUITEM "CLSCTX_INPROC_&HANDLER", IDM_FLAG_INHANDL + MENUITEM "CLSCTX_&LOCAL_SERVER", IDM_FLAG_LOCSERV,CHECKED + MENUITEM "CLSCTX_&REMOTE_SERVER", IDM_FLAG_REMSERV + } + MENUITEM SEPARATOR + MENUITEM "Ïðîñìîòð &Type info", IDM_TYPEINFO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Create &Instance", IDM_CREATEINST, GRAYED + MENUITEM "Create Instance &On...", IDM_CREATEINSTON, GRAYED + MENUITEM "&Release Instance", IDM_RELEASEINST, GRAYED + MENUITEM SEPARATOR + MENUITEM "Êîïèðîâàòü C&LSID â áóôåð", IDM_COPYCLSID, GRAYED + MENUITEM "Êîïèðîâàòü &HTML object Tag â áóôåð", IDM_HTMLTAG, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Âèä...", IDM_VIEW, GRAYED + } + POPUP "&Âèä" + { + MENUITEM "&Ðåæèì ýêñïåðòà", IDM_EXPERT,CHECKED + MENUITEM SEPARATOR + MENUITEM "&Hidden component categories", IDM_HIDDEN, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Ïàíåëü èíñòðóìåíòîâ", IDM_TOOLBAR,CHECKED + MENUITEM "&Ñòðîêà ñîñòîÿíèÿ", IDM_STATUSBAR,CHECKED + MENUITEM SEPARATOR + MENUITEM "&Îáíîâèòü\tF5", IDM_REFRESH + } + POPUP "&Ïîìîùü" + { + MENUITEM "&Î ïðîãðàììå...", IDM_ABOUT + } +} + +IDM_TYPELIB MENU +{ + POPUP "&Ôàéë" + { + MENUITEM "&Ñîõðàíèòü êàê...", IDM_SAVEAS + MENUITEM "&Çàêðûòü", IDM_CLOSE + } + POPUP "&Âèä" + { + MENUITEM "&Group by type kind", IDM_GROUP + MENUITEM SEPARATOR + MENUITEM "&Ïàíåëü èíñòðóìåíòîâ", IDM_TOOLBAR + MENUITEM "&Ñòðîêà ñîñòîÿíèÿ", IDM_STATUSBAR,CHECKED + } +} + +STRINGTABLE +{ + IDS_APPNAME "OleView" + IDS_APPTITLE "OleView" + IDS_READY "Ãîòîâî" + IDS_ABOUT "OleView - OLE/COM Object Viewer" + IDS_ABOUTVER "âåðñèÿ 1.0" + IDS_TYPELIBTITLE "ITypeLib viewer" + IDS_OPEN "Îòêðûòü" + IDS_OPEN_TYPELIB_FILTER "Ôàéëû TypeLib (*.tlb;*.olb;*.dll;*.ocx;*.exe)\0*.tlb;*.olb;*.dll;*.ocx;*.exe\0All Files (*.*)\0*.*\0\0" + + IDM_BIND, "Bind to file via a File Moniker" + IDM_TYPELIB, "Open a TypeLib file and view the contents" + IDM_SYSCONF, "Change machine wide Distributed COM settings" + IDM_REGEDIT, "Çàïóñòèòü Ðåäàêòîð ðååñòðà Wine" + IDM_EXIT, "Âûéòè èç ïðèëîæåíèÿ ñ ïðåäëîæåíèåì ñîõðàíèòü èçìåíåíèÿ" + IDM_CREATEINST, "Create an instance of the selected object" + IDM_CREATEINSTON, "Create an instance of the selected object on a specyfic machine" + IDM_RELEASEINST, "Release the currently selected object instance" + IDM_COPYCLSID, "Êîïèðîâàòü GUID âûäåëåííîãî ýëåìåíòà â áóôåð" + IDM_VIEW, "Display the viewer for the selected item" + IDM_FLAG_INSERV, "Èñïîëüçîâàòü CLSCTX_INPROC_SERVER ïðè âûçîâå CoGetClassObject" + IDM_FLAG_INHANDL, "Èñïîëüçîâàòü CLSCTX_INPROC_HANDLER ïðè âûçîâå CoGetClassObject" + IDM_FLAG_LOCSERV, "Èñïîëüçîâàòü CLSCTX_LOCAL_SERVER ïðè âûçîâå CoGetClassObject" + IDM_FLAG_REMSERV, "Èñïîëüçîâàòü CLSCTX_REMOTE_SERVER ïðè âûçîâå CoGetClassObject" + IDM_EXPERT, "Ïåðåêëþ÷èòüñÿ ìåæäó ðåæèìîì ýêñïåðò/íîâè÷îê" + IDM_HIDDEN, "Toggle the display of component categories that are not meant to be visible" + IDM_TOOLBAR, "Ïîêàçàòü/ñêðûòü ïàíåëü èíñòðóìåíòîâ" + IDM_STATUSBAR, "Ïîêàçàòü/ñêðûòü ñòðîêó ñîñòîÿíèÿ" + IDM_REFRESH, "Îáíîâèòü âñå ñïèñêè" + IDM_ABOUT, "Îòîáðàçèòü èíôîðìàöèþ î ïðîãðàììå, íîìåð âåðñèè è êîïèðàéò" + + IDM_SAVEAS, "Ñîõðàíèòü êàê .IDL èëè .H ôàéë" + IDM_CLOSE, "Çàêðûòü îêíî" + IDM_GROUP, "Group typeinfos by kind" + + IDS_TREE_OC, "ObjectClasses" + IDS_TREE_GBCC, "Grouped by Component Category" + IDS_TREE_O1O, "Îáúåêòû OLE 1.0" + IDS_TREE_CLO, "Îáúåêòû áèáëèîòåêè COM" + IDS_TREE_AO, "Âñå îáúåêòû" + IDS_TREE_AID, "ID ïðèëîæåíèÿ" + IDS_TREE_TL, "Type Libraries" + IDS_TL_VER, "âåð." + IDS_TREE_I, "Èíòåðôåéñû" + + IDS_TAB_REG, "Ðååñòð" + IDS_TAB_IMPL, "Implementation" + IDS_TAB_ACTIV, "Activation" + + IDS_CGCOFAIL, "CoGetClassObject failed." + IDS_ERROR_UNKN, "Íåèçâåñòíàÿ îøèáêà" + IDS_TRUE, "True" + IDS_FALSE, "False" + IDS_BYTES, "áàéò" + + IDS_ERROR_LOADTYPELIB, "LoadTypeLib( %s ) failed ($%x)" + IDS_INHERITINTERFACES, "Inherited Interfaces" +} + +DLG_CREATEINSTON DIALOG DISCARDABLE 0, 0, 250, 41 +STYLE DS_MODALFRAME | DS_NOIDLEMSG | WS_CAPTION | WS_SYSMENU +CAPTION "Ïîäêëþ÷èòüñÿ ê äðóãîìó êîìïüþòåðó" +FONT 8, "MS Shell Dlg" +{ + LTEXT "&Èìÿ êîìïüþòåðà:", IDIGNORE, 5, 6, 190, 8 + EDITTEXT IDC_MACHINE, 5, 16, 190, 12, WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL + DEFPUSHBUTTON "&OK", IDOK, 200, 5, 45, 14 + PUSHBUTTON "&Îòìåíà", IDCANCEL, 200, 22, 45, 14 +} + +DLG_SYSCONF DIALOG DISCARDABLE 0, 0, 170, 100 +STYLE DS_MODALFRAME | DS_NOIDLEMSG | WS_CAPTION | WS_SYSMENU +CAPTION "Êîíôèãóðàöèÿ ñèñòåìû" +FONT 8, "MS Shell Dlg" +{ + LTEXT "Íàñòðîéêè ñèñòåìû", IDIGNORE, 5, 6, 160, 8 + CHECKBOX "&Ðàçðåøèòü ðàñïðåäåëåííûé COM", IDC_ENABLEDCOM, 5, 20, 160, 10, WS_TABSTOP | WS_GROUP | BS_AUTOCHECKBOX + CHECKBOX "Ðàçðåøèòü &óäàëåííûå ïîäêëþ÷åíèÿ (òîëüêî Win95)", IDC_ENABLEREMOTE, 5, 35, 160, 10, WS_TABSTOP | WS_GROUP | BS_AUTOCHECKBOX + LTEXT "Ýòè íàñòðîéêè èçìåíÿþò òîëüêî çíà÷åíèÿ ðååñòðà è íå îêàçûâàþò âëèÿíèÿ íà ïðîèçâîäèòåëüíîñòü Wine.", IDIGNORE, 5, 50, 160, 40 + DEFPUSHBUTTON "&OK", IDOK, 70, 80, 45, 14 + PUSHBUTTON "&Îòìåíà", IDCANCEL, 120, 80, 45, 14 +} + +DLG_DEFAULT_IV DIALOG DISCARDABLE 0, 0, 280, 50 +STYLE DS_MODALFRAME | DS_NOIDLEMSG | WS_CAPTION | WS_SYSMENU +CAPTION "Default Interface Viewer" +FONT 8, "MS Shell Dlg" +{ + LTEXT "Èíòåðôåéñ", IDIGNORE, 5, 6, 50, 8 + LTEXT "", IDC_LABEL, 60, 6, 145, 8 + LTEXT "IID:", IDIGNORE, 5, 16, 50, 8 + LTEXT "", IDC_IDENTIFIER, 60, 16, 165, 8 + DEFPUSHBUTTON "&Çàêðûòü", IDCANCEL, 230, 6, 45, 14 + PUSHBUTTON "&View Type Info", IDC_VIEWTYPEINFO, 6, 31, 70, 14, WS_DISABLED +} + +DLG_IPERSIST_IV DIALOG DISCARDABLE 0, 0, 280, 29 +STYLE DS_MODALFRAME | DS_NOIDLEMSG | WS_CAPTION | WS_SYSMENU +CAPTION "IPersist Interface Viewer" +FONT 8, "MS Shell Dlg" +{ + LTEXT "Èìÿ êëàññà:", IDIGNORE, 5, 6, 50, 8 + LTEXT "", IDC_LABEL, 60, 6, 145, 8 + LTEXT "CLSID:", IDIGNORE, 5, 16, 50, 8 + LTEXT "", IDC_IDENTIFIER, 60, 16, 165, 8 + DEFPUSHBUTTON "&Çàêðûòü", IDCANCEL, 230, 6, 45, 14 +} + +DLG_IPERSISTSTREAM_IV DIALOG DISCARDABLE 0, 0, 280, 68 +STYLE DS_MODALFRAME | DS_NOIDLEMSG | WS_CAPTION | WS_SYSMENU +CAPTION "IPersistStream Interface Viewer" +FONT 8, "MS Shell Dlg" +{ + LTEXT "Èìÿ êëàññà:", IDIGNORE, 5, 6, 50, 8 + LTEXT "", IDC_LABEL, 60, 6, 145, 8 + LTEXT "CLSID:", IDIGNORE, 5, 16, 50, 8 + LTEXT "", IDC_IDENTIFIER, 60, 16, 165, 8 + DEFPUSHBUTTON "&Çàêðûòü", IDCANCEL, 230, 6, 45, 14 + PUSHBUTTON "&IsDirty", IDC_ISDIRTY_BUTTON, 6, 31, 50, 14 + LTEXT "???", IDC_ISDIRTY, 60, 34, 145, 8 + PUSHBUTTON "&GetSizeMax", IDC_GETSIZEMAX_BUTTON, 6, 49, 50, 14 + LTEXT "???", IDC_GETSIZEMAX, 60, 52, 145, 8 +} diff --git a/programs/oleview/rsrc.rc b/programs/oleview/rsrc.rc index 96043464bc8..5b4c7812fa4 100644 --- a/programs/oleview/rsrc.rc +++ b/programs/oleview/rsrc.rc @@ -31,6 +31,7 @@ #include "Nl.rc" #include "No.rc" #include "Pl.rc" +#include "Ru.rc" LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL diff --git a/programs/regedit/edit.c b/programs/regedit/edit.c index 40a08348ed6..5135dea77f4 100644 --- a/programs/regedit/edit.c +++ b/programs/regedit/edit.c @@ -107,8 +107,8 @@ static BOOL change_dword_base(HWND hwndDlg, BOOL toHex) DWORD val; if (!GetDlgItemText(hwndDlg, IDC_VALUE_DATA, buf, COUNT_OF(buf))) return FALSE; - if (!_stscanf(buf, toHex ? "%d" : "%x", &val)) return FALSE; - wsprintf(buf, toHex ? "%lx" : "%ld", val); + if (!_stscanf(buf, toHex ? "%u" : "%x", &val)) return FALSE; + wsprintf(buf, toHex ? "%x" : "%u", val); return SetDlgItemText(hwndDlg, IDC_VALUE_DATA, buf); } @@ -305,10 +305,10 @@ BOOL ModifyValue(HWND hwnd, HKEY hKeyRoot, LPCTSTR keyPath, LPCTSTR valueName) else error_code_messagebox(hwnd, lRet); } } else if ( type == REG_DWORD ) { - wsprintf(stringValueData, isDecimal ? "%ld" : "%lx", *((DWORD*)stringValueData)); + wsprintf(stringValueData, isDecimal ? "%u" : "%x", *((DWORD*)stringValueData)); if (DialogBox(0, MAKEINTRESOURCE(IDD_EDIT_DWORD), hwnd, modify_dlgproc) == IDOK) { DWORD val; - if (_stscanf(stringValueData, isDecimal ? "%d" : "%x", &val)) { + if (_stscanf(stringValueData, isDecimal ? "%u" : "%x", &val)) { lRet = RegSetValueEx(hKey, valueName, 0, type, (BYTE*)&val, sizeof(val)); if (lRet == ERROR_SUCCESS) result = TRUE; else error_code_messagebox(hwnd, lRet); diff --git a/programs/rpcss/Makefile.in b/programs/rpcss/Makefile.in index 7a991a9a8fd..2afb6f70c20 100644 --- a/programs/rpcss/Makefile.in +++ b/programs/rpcss/Makefile.in @@ -7,12 +7,12 @@ APPMODE = -mconsole IMPORTS = rpcrt4 kernel32 ntdll C_SRCS = \ - epmap_server.c \ - irotp.c \ - np_server.c \ - rpcss_main.c + epmp.c \ + irotp.c \ + rpcss_main.c IDL_S_SRCS = \ + epm.idl \ irot.idl @MAKE_PROG_RULES@ diff --git a/dlls/rpcrt4/rpcss_np_client.h b/programs/rpcss/epm.idl similarity index 73% rename from dlls/rpcrt4/rpcss_np_client.h rename to programs/rpcss/epm.idl index b00066de518..67fad348c88 100644 --- a/dlls/rpcrt4/rpcss_np_client.h +++ b/programs/rpcss/epm.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Greg Turner + * Copyright 2008 Robert Shearman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,11 +16,4 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H - -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLIENT_H */ +#include "wine/epm.idl" diff --git a/programs/rpcss/epmap_server.c b/programs/rpcss/epmap_server.c deleted file mode 100644 index e96b3a10e41..00000000000 --- a/programs/rpcss/epmap_server.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * RPC endpoint mapper server - * - * Copyright (C) 2001 Ove Kåven, TransGaming Technologies Inc, - * Copyright (C) 2002 Greg Turner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include - -#include "rpcss.h" -#include "rpc.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -struct epmap_entry -{ - struct epmap_entry *next; - RPC_SYNTAX_IDENTIFIER iface; - UUID object; - char *protseq; - char *endpoint; -}; - -static struct epmap_entry *epmap; - -static const UUID nil_object; - -static char *mystrdup(const char *str) { - char *rval; - rval = LocalAlloc(LPTR, strlen(str)+1); - CopyMemory(rval, str, strlen(str)+1); - return rval; -} - -static struct epmap_entry *find_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, - const char *protseq, const UUID *object) -{ - struct epmap_entry *map; - for (map=epmap; map; map=map->next) { - if (memcmp(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue; - if (memcmp(&map->object, object, sizeof(UUID))) continue; - if (strcmp(map->protseq, protseq)) continue; - WINE_TRACE("found.\n"); - return map; - } - WINE_TRACE("not found.\n"); - return NULL; -} - -static void register_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq, - const char *endpoint, const UUID *objects, int objcount, - int no_replace) -{ - int c; - - WINE_TRACE("(protseq == %s, endpoint == %s, objcount == %i, no_replace == %i)\n", - wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), objcount, no_replace); - - if (!objcount) { - objects = &nil_object; - objcount = 1; - } - - for (c=0; cendpoint); - } - else { - map = LocalAlloc(LPTR, sizeof(struct epmap_entry)); - memcpy(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER)); - memcpy(&map->object, &objects[c], sizeof(UUID)); - map->protseq = mystrdup(protseq); - map->next = epmap; - epmap = map; - } - WINE_TRACE(" mapping endpoint (protseq == %s, endpoint == %s, uuid == %s)\n", - wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), wine_dbgstr_guid(&objects[c])); - map->endpoint = mystrdup(endpoint); - } -} - -static void unregister_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq, - const char *endpoint, const UUID *objects, int objcount) -{ - struct epmap_entry *map, *prev, *nprev, *next; - int c; - - WINE_TRACE("(protseq == %s, endpoint == %s, objcount == %i)\n", - wine_dbgstr_a(protseq), wine_dbgstr_a(endpoint), objcount); - - if (!objcount) { - objects = &nil_object; - objcount = 1; - } - prev=NULL; - nprev=NULL; - map=epmap; - while(map) { - next = map->next; - nprev = map; - if (memcmp(&map->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) goto cont; - for (c=0; cobject, &objects[c], sizeof(UUID))) break; - if (c==objcount) goto cont; - if (strcmp(map->protseq, protseq)) goto cont; - - WINE_TRACE(" unmapping: (protseq == %s, endpoint == %s, uuid == %s)\n", - wine_dbgstr_a(map->protseq), wine_dbgstr_a(map->endpoint), - wine_dbgstr_guid(&map->object)); - - if (prev) prev->next = map->next; - else epmap = map->next; - nprev = prev; - - LocalFree(map->protseq); - LocalFree(map->endpoint); - LocalFree(map); - - cont: - - prev = nprev; - map = next; - } -} - -static void resolve_endpoint(const RPC_SYNTAX_IDENTIFIER *iface, const char *protseq, - const UUID *object, char *rslt_ep) -{ - size_t len; - struct epmap_entry *map; - - if (!(map = find_endpoint(iface, protseq, object))) return; - - len = min( MAX_RPCSS_NP_REPLY_STRING_LEN, strlen(map->endpoint)+1 ); - if (len) memcpy(rslt_ep, map->endpoint, len); -} - -static const char *get_string(const char**ptr, const char*end) -{ - const char *str = *ptr, *nptr = str; - - while (nptr < end && *nptr) nptr++; - if (nptr == end) - return NULL; - *ptr = nptr + 1; - return str; -} - -BOOL RPCSS_EpmapEmpty(void) -{ - return (!epmap); -} - -void RPCSS_RegisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count, - int binding_count, int no_replace, char *vardata, long vardata_size) -{ - const char *data = vardata; - const char *end = data + vardata_size; - const UUID *objects = (const UUID *)data; - int c; - - data += object_count * sizeof(UUID); - for (c=0; c < binding_count; c++) { - const char *protseq = get_string(&data, end); - const char *endpoint = get_string(&data, end); - if (protseq && endpoint) - register_endpoint(&iface, protseq, endpoint, objects, object_count, no_replace); - } -} - -void RPCSS_UnregisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count, - int binding_count, char *vardata, long vardata_size) -{ - const char *data = vardata; - const char *end = data + vardata_size; - const UUID *objects = (const UUID *)data; - int c; - - data += object_count * sizeof(UUID); - for (c=0; c < binding_count; c++) { - const char *protseq = get_string(&data, end); - const char *endpoint = get_string(&data, end); - if (protseq && endpoint) - unregister_endpoint(&iface, protseq, endpoint, objects, object_count); - } -} - -void RPCSS_ResolveRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, UUID object, char *protseq, char *rslt_ep) -{ - resolve_endpoint(&iface, protseq, &object, rslt_ep); -} diff --git a/programs/rpcss/epmp.c b/programs/rpcss/epmp.c new file mode 100644 index 00000000000..cf14be8c3d7 --- /dev/null +++ b/programs/rpcss/epmp.c @@ -0,0 +1,283 @@ +/* + * Endpoint Mapper + * + * Copyright (C) 2007 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 "epm.h" + +#include "wine/debug.h" +#include "wine/list.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +struct registered_ept_entry +{ + struct list entry; + GUID object; + RPC_SYNTAX_IDENTIFIER iface; + RPC_SYNTAX_IDENTIFIER syntax; + char *protseq; + char *endpoint; + char *address; + char annotation[ept_max_annotation_size]; +}; + +static struct list registered_ept_entry_list = LIST_INIT(registered_ept_entry_list); + +static CRITICAL_SECTION csEpm; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &csEpm, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": csEpm") } +}; +static CRITICAL_SECTION csEpm = { &critsect_debug, -1, 0, 0, 0, 0 }; + +static const UUID nil_object; + +/* must be called inside csEpm */ +static void delete_registered_ept_entry(struct registered_ept_entry *entry) +{ + I_RpcFree(entry->protseq); + I_RpcFree(entry->endpoint); + I_RpcFree(entry->address); + list_remove(&entry->entry); + HeapFree(GetProcessHeap(), 0, entry); +} + +static struct registered_ept_entry *find_ept_entry( + const RPC_SYNTAX_IDENTIFIER *iface, const RPC_SYNTAX_IDENTIFIER *syntax, + const char *protseq, const char *endpoint, const char *address, + const UUID *object) +{ + struct registered_ept_entry *entry; + LIST_FOR_EACH_ENTRY(entry, ®istered_ept_entry_list, struct registered_ept_entry, entry) + { + if (memcmp(&entry->iface, iface, sizeof(RPC_SYNTAX_IDENTIFIER))) continue; + if (memcmp(&entry->syntax, syntax, sizeof(RPC_SYNTAX_IDENTIFIER))) continue; + if (strcmp(entry->protseq, protseq)) continue; + if (memcmp(&entry->object, object, sizeof(UUID))) continue; + WINE_TRACE("found entry with iface %d.%d %s, syntax %d.%d %s, protseq %s, object %s\n", + entry->iface.SyntaxVersion.MajorVersion, entry->iface.SyntaxVersion.MinorVersion, + wine_dbgstr_guid(&entry->iface.SyntaxGUID), + entry->syntax.SyntaxVersion.MajorVersion, entry->syntax.SyntaxVersion.MinorVersion, + wine_dbgstr_guid(&entry->syntax.SyntaxGUID), protseq, + wine_dbgstr_guid(&entry->object)); + return entry; + } + WINE_TRACE("not found\n"); + return NULL; +} + +void __RPC_USER ept_lookup_handle_t_rundown(ept_lookup_handle_t entry_handle) +{ + WINE_FIXME("%p", entry_handle); +} + +void ept_insert(handle_t h, + unsigned32 num_ents, + ept_entry_t entries[], + boolean32 replace, + error_status_t *status) +{ + unsigned32 i; + RPC_STATUS rpc_status; + + WINE_TRACE("(%p, %lu, %p, %lu, %p)\n", h, num_ents, entries, replace, status); + + *status = RPC_S_OK; + + EnterCriticalSection(&csEpm); + + for (i = 0; i < num_ents; i++) + { + struct registered_ept_entry *entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry)); + if (!entry) + { + /* FIXME: cleanup code to delete added entries */ + *status = EPT_S_CANT_PERFORM_OP; + break; + } + list_init(&entry->entry); + memcpy(entry->annotation, entries[i].annotation, sizeof(entries[i].annotation)); + rpc_status = TowerExplode(entries[i].tower, &entry->iface, &entry->syntax, + &entry->protseq, &entry->endpoint, + &entry->address); + if (rpc_status != RPC_S_OK) + { + *status = rpc_status; + break; /* FIXME: more cleanup? */ + } + + entry->object = entries[i].object; + + if (replace) + { + /* FIXME: correct find algorithm */ + struct registered_ept_entry *old_entry = find_ept_entry(&entry->iface, &entry->syntax, entry->protseq, entry->endpoint, entry->address, &entry->object); + if (old_entry) delete_registered_ept_entry(old_entry); + } + list_add_tail(®istered_ept_entry_list, &entry->entry); + } + + LeaveCriticalSection(&csEpm); +} + +void ept_delete(handle_t h, + unsigned32 num_ents, + ept_entry_t entries[], + error_status_t *status) +{ + unsigned32 i; + RPC_STATUS rpc_status; + + *status = RPC_S_OK; + + WINE_TRACE("(%p, %lu, %p, %p)\n", h, num_ents, entries, status); + + EnterCriticalSection(&csEpm); + + for (i = 0; i < num_ents; i++) + { + struct registered_ept_entry *entry; + RPC_SYNTAX_IDENTIFIER iface, syntax; + char *protseq; + char *endpoint; + char *address; + rpc_status = TowerExplode(entries[i].tower, &iface, &syntax, &protseq, + &endpoint, &address); + if (rpc_status != RPC_S_OK) + break; + entry = find_ept_entry(&iface, &syntax, protseq, endpoint, address, &entries[i].object); + if (entry) + delete_registered_ept_entry(entry); + else + { + *status = EPT_S_NOT_REGISTERED; + break; + } + I_RpcFree(protseq); + I_RpcFree(endpoint); + I_RpcFree(address); + } + + LeaveCriticalSection(&csEpm); +} + +void ept_lookup(handle_t h, + unsigned32 inquiry_type, + uuid_p_t object, + rpc_if_id_p_t interface_id, + unsigned32 vers_option, + ept_lookup_handle_t *entry_handle, + unsigned32 max_ents, + unsigned32 *num_ents, + ept_entry_t entries[], + error_status_t *status) +{ + WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status); + + *status = EPT_S_CANT_PERFORM_OP; +} + +void ept_map(handle_t h, + uuid_p_t object, + twr_p_t map_tower, + ept_lookup_handle_t *entry_handle, + unsigned32 max_towers, + unsigned32 *num_towers, + twr_p_t *towers, + error_status_t *status) +{ + RPC_STATUS rpc_status; + RPC_SYNTAX_IDENTIFIER iface, syntax; + char *protseq; + struct registered_ept_entry *entry; + + *status = RPC_S_OK; + *num_towers = 0; + + WINE_TRACE("(%p, %p, %p, %p, %lu, %p, %p, %p)\n", h, object, map_tower, + entry_handle, max_towers, num_towers, towers, status); + + rpc_status = TowerExplode(map_tower, &iface, &syntax, &protseq, + NULL, NULL); + if (rpc_status != RPC_S_OK) + { + *status = rpc_status; + return; + } + + EnterCriticalSection(&csEpm); + + LIST_FOR_EACH_ENTRY(entry, ®istered_ept_entry_list, struct registered_ept_entry, entry) + { + if (IsEqualGUID(&entry->iface.SyntaxGUID, &iface.SyntaxGUID) && + (entry->iface.SyntaxVersion.MajorVersion == iface.SyntaxVersion.MajorVersion) && + (entry->iface.SyntaxVersion.MinorVersion >= iface.SyntaxVersion.MinorVersion) && + !memcmp(&entry->syntax, &syntax, sizeof(syntax)) && + !strcmp(entry->protseq, protseq) && + ((!object && IsEqualGUID(&entry->object, &nil_object)) || IsEqualGUID(object, &entry->object))) + { + if (*num_towers < max_towers) + { + rpc_status = TowerConstruct(&entry->iface, &entry->syntax, + entry->protseq, entry->endpoint, + entry->address, + &towers[*num_towers]); + if (rpc_status != RPC_S_OK) + { + *status = rpc_status; + break; /* FIXME: more cleanup? */ + } + } + (*num_towers)++; + } + } + + LeaveCriticalSection(&csEpm); +} + +void ept_lookup_handle_free(handle_t h, + ept_lookup_handle_t *entry_handle, + error_status_t *status) +{ + WINE_FIXME("(%p, %p, %p): stub\n", h, entry_handle, status); + + *status = EPT_S_CANT_PERFORM_OP; +} + +void ept_inq_object(handle_t h, + GUID *ept_object, + error_status_t *status) +{ + WINE_FIXME("(%p, %p, %p): stub\n", h, ept_object, status); + + *status = EPT_S_CANT_PERFORM_OP; +} + +void ept_mgmt_delete(handle_t h, + boolean32 object_speced, + uuid_p_t object, + twr_p_t tower, + error_status_t *status) +{ + WINE_FIXME("(%p, %ld, %p, %p, %p): stub\n", h, object_speced, object, tower, status); + + *status = EPT_S_CANT_PERFORM_OP; +} diff --git a/programs/rpcss/np_server.c b/programs/rpcss/np_server.c deleted file mode 100644 index 1ad22c428aa..00000000000 --- a/programs/rpcss/np_server.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - * RPCSS named pipe server - * - * Copyright (C) 2002 Greg Turner - * - * 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 "rpcss.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -static HANDLE np_server_end; -static HANDLE np_server_work_event; -static CRITICAL_SECTION np_server_cs; -static LONG srv_thread_count; -static BOOL server_live; - -LONG RPCSS_SrvThreadCount(void) -{ - return srv_thread_count; -} - -BOOL RPCSS_UnBecomePipeServer(void) -{ - WINE_TRACE("\n"); - - WINE_TRACE("shutting down pipe.\n"); - server_live = FALSE; - if (!CloseHandle(np_server_end)) - WINE_WARN("Failed to close named pipe.\n"); - if (!CloseHandle(np_server_work_event)) - WINE_WARN("Failed to close the event handle.\n"); - DeleteCriticalSection(&np_server_cs); - - return TRUE; -} - -static void RPCSS_ServerProcessRANMessage(PRPCSS_NP_MESSAGE pMsg, PRPCSS_NP_REPLY pReply) -{ - WINE_TRACE("\n"); - pReply->as_uint = 0; -} - -static void RPCSS_ServerProcessREGISTEREPMessage(PRPCSS_NP_MESSAGE pMsg, PRPCSS_NP_REPLY pReply, - char *vardata) -{ - WINE_TRACE("\n"); - - RPCSS_RegisterRpcEndpoints( - pMsg->message.registerepmsg.iface, - pMsg->message.registerepmsg.object_count, - pMsg->message.registerepmsg.binding_count, - pMsg->message.registerepmsg.no_replace, - vardata, - pMsg->vardata_payload_size - ); - - /* no reply */ - pReply->as_uint = 0; -} - -static void RPCSS_ServerProcessUNREGISTEREPMessage(PRPCSS_NP_MESSAGE pMsg, - PRPCSS_NP_REPLY pReply, char *vardata) -{ - WINE_TRACE("\n"); - - RPCSS_UnregisterRpcEndpoints( - pMsg->message.unregisterepmsg.iface, - pMsg->message.unregisterepmsg.object_count, - pMsg->message.unregisterepmsg.binding_count, - vardata, - pMsg->vardata_payload_size - ); - - /* no reply */ - pReply->as_uint = 0; -} - -static void RPCSS_ServerProcessRESOLVEEPMessage(PRPCSS_NP_MESSAGE pMsg, - PRPCSS_NP_REPLY pReply, char *vardata) -{ - WINE_TRACE("\n"); - - /* for now, reply is placed into *pReply.as_string, on success, by RPCSS_ResolveRpcEndpoints */ - ZeroMemory(pReply->as_string, MAX_RPCSS_NP_REPLY_STRING_LEN); - RPCSS_ResolveRpcEndpoints( - pMsg->message.resolveepmsg.iface, - pMsg->message.resolveepmsg.object, - vardata, - pReply->as_string - ); -} - -static void RPCSS_ServerProcessMessage(PRPCSS_NP_MESSAGE pMsg, PRPCSS_NP_REPLY pReply, char *vardata) -{ - WINE_TRACE("\n"); - ZeroMemory(pReply, sizeof(*pReply)); - switch (pMsg->message_type) { - case RPCSS_NP_MESSAGE_TYPEID_RANMSG: - RPCSS_ServerProcessRANMessage(pMsg, pReply); - break; - case RPCSS_NP_MESSAGE_TYPEID_REGISTEREPMSG: - RPCSS_ServerProcessREGISTEREPMessage(pMsg, pReply, vardata); - break; - case RPCSS_NP_MESSAGE_TYPEID_UNREGISTEREPMSG: - RPCSS_ServerProcessUNREGISTEREPMessage(pMsg, pReply, vardata); - break; - case RPCSS_NP_MESSAGE_TYPEID_RESOLVEEPMSG: - RPCSS_ServerProcessRESOLVEEPMessage(pMsg, pReply, vardata); - break; - default: - WINE_ERR("Message type unknown!! No action taken.\n"); - } -} - -/* each message gets its own thread. this is it. */ -static DWORD WINAPI HandlerThread(LPVOID lpvPipeHandle) -{ - RPCSS_NP_MESSAGE msg, vardata_payload_msg; - char *c, *vardata = NULL; - RPCSS_NP_REPLY reply; - DWORD bytesread, written; - BOOL success, had_payload = FALSE; - HANDLE mypipe; - - mypipe = (HANDLE) lpvPipeHandle; - - WINE_TRACE("mypipe: %p\n", mypipe); - - success = ReadFile( - mypipe, /* pipe handle */ - (char *) &msg, /* message buffer */ - sizeof(RPCSS_NP_MESSAGE), /* message buffer size */ - &bytesread, /* receives number of bytes read */ - NULL /* not overlapped */ - ); - - if (msg.vardata_payload_size) { - had_payload = TRUE; - /* this fudge space allows us not to worry about exceeding the buffer space - on the last read */ - vardata = LocalAlloc(LPTR, (msg.vardata_payload_size) + VARDATA_PAYLOAD_BYTES); - if (!vardata) { - WINE_ERR("vardata memory allocation failure.\n"); - success = FALSE; - } else { - for ( c = vardata; (c - vardata) < msg.vardata_payload_size; - c += VARDATA_PAYLOAD_BYTES) { - success = ReadFile( - mypipe, - (char *) &vardata_payload_msg, - sizeof(RPCSS_NP_MESSAGE), - &bytesread, - NULL - ); - if ( (!success) || (bytesread != sizeof(RPCSS_NP_MESSAGE)) || - (vardata_payload_msg.message_type != RPCSS_NP_MESSAGE_TYPEID_VARDATAPAYLOADMSG) ) { - WINE_ERR("vardata payload read failure! (s=%s,br=%d,mt=%u,mt_exp=%u\n", - success ? "TRUE" : "FALSE", bytesread, - vardata_payload_msg.message_type, RPCSS_NP_MESSAGE_TYPEID_VARDATAPAYLOADMSG); - success = FALSE; - break; - } - CopyMemory(c, vardata_payload_msg.message.vardatapayloadmsg.payload, VARDATA_PAYLOAD_BYTES); - WINE_TRACE("payload read.\n"); - } - } - } - - if (success && (bytesread == sizeof(RPCSS_NP_MESSAGE))) { - WINE_TRACE("read success.\n"); - /* process the message and send a reply, serializing requests. */ - EnterCriticalSection(&np_server_cs); - WINE_TRACE("processing message.\n"); - RPCSS_ServerProcessMessage(&msg, &reply, vardata); - LeaveCriticalSection(&np_server_cs); - - if (had_payload) LocalFree(vardata); - - WINE_TRACE("message processed, sending reply....\n"); - - success = WriteFile( - mypipe, /* pipe handle */ - (char *) &reply, /* reply buffer */ - sizeof(RPCSS_NP_REPLY), /* reply buffer size */ - &written, /* receives number of bytes written */ - NULL /* not overlapped */ - ); - - if ( (!success) || (written != sizeof(RPCSS_NP_REPLY)) ) - WINE_WARN("Message reply failed. (success=%d, br=%d)\n", success, written); - else - WINE_TRACE("Reply sent successfully.\n"); - } else - WINE_WARN("Message receipt failed.\n"); - - FlushFileBuffers(mypipe); - DisconnectNamedPipe(mypipe); - CloseHandle(mypipe); - InterlockedDecrement(&srv_thread_count); - return 0; -} - -static DWORD WINAPI NPMainWorkThread(LPVOID ignored) -{ - BOOL connected; - HANDLE hthread, master_mutex = RPCSS_GetMasterMutex(); - DWORD threadid, wait_result; - - WINE_TRACE("\n"); - - while (server_live) { - connected = ConnectNamedPipe(np_server_end, NULL) ? - TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); - - if (connected) { - /* is "work" the act of connecting pipes, or the act of serving - requests successfully? for now I will make it the former. */ - if (!SetEvent(np_server_work_event)) - WINE_WARN("failed to signal np_server_work_event.\n"); - - /* Create a thread for this client. */ - InterlockedIncrement(&srv_thread_count); - hthread = CreateThread( - NULL, /* no security attribute */ - 0, /* default stack size */ - HandlerThread, - (LPVOID) np_server_end, /* thread parameter */ - 0, /* not suspended */ - &threadid /* returns thread ID (not used) */ - ); - - if (hthread) { - WINE_TRACE("Spawned handler thread: %p\n", hthread); - CloseHandle(hthread); - - /* for safety's sake, hold the mutex while we switch the pipe */ - - wait_result = WaitForSingleObject(master_mutex, MASTER_MUTEX_TIMEOUT); - - switch (wait_result) { - case WAIT_ABANDONED: /* ? */ - case WAIT_OBJECT_0: - /* we have ownership */ - break; - case WAIT_FAILED: - case WAIT_TIMEOUT: - default: - /* huh? */ - wait_result = WAIT_FAILED; - } - - if (wait_result == WAIT_FAILED) { - WINE_ERR("Couldn't enter master mutex. Expect problems.\n"); - } else { - /* now create a new named pipe instance to listen on */ - np_server_end = CreateNamedPipe( - NAME_RPCSS_NAMED_PIPE, /* pipe name */ - PIPE_ACCESS_DUPLEX, /* pipe open mode */ - PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, /* pipe-specific modes */ - PIPE_UNLIMITED_INSTANCES, /* maximum instances */ - sizeof(RPCSS_NP_REPLY), /* output buffer size */ - sizeof(RPCSS_NP_MESSAGE), /* input buffer size */ - 2000, /* time-out interval */ - NULL /* SD */ - ); - - if (np_server_end == INVALID_HANDLE_VALUE) { - WINE_ERR("Failed to recreate named pipe!\n"); - /* not sure what to do? */ - assert(FALSE); - } - - if (!ReleaseMutex(master_mutex)) - WINE_ERR("Uh oh. Couldn't leave master mutex. Expect deadlock.\n"); - } - } else { - WINE_ERR("Failed to spawn handler thread!\n"); - DisconnectNamedPipe(np_server_end); - InterlockedDecrement(&srv_thread_count); - } - } - } - WINE_TRACE("Server thread shutdown.\n"); - return 0; -} - -static HANDLE RPCSS_NPConnect(void) -{ - HANDLE the_pipe; - DWORD dwmode, wait_result; - HANDLE master_mutex = RPCSS_GetMasterMutex(); - - WINE_TRACE("\n"); - - while (TRUE) { - - wait_result = WaitForSingleObject(master_mutex, MASTER_MUTEX_TIMEOUT); - switch (wait_result) { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: - break; - case WAIT_FAILED: - case WAIT_TIMEOUT: - default: - WINE_ERR("This should never happen: couldn't enter mutex.\n"); - return NULL; - } - - /* try to open the client side of the named pipe. */ - the_pipe = CreateFileA( - NAME_RPCSS_NAMED_PIPE, /* pipe name */ - GENERIC_READ | GENERIC_WRITE, /* r/w access */ - 0, /* no sharing */ - NULL, /* no security attributes */ - OPEN_EXISTING, /* open an existing pipe */ - 0, /* default attributes */ - NULL /* no template file */ - ); - - if (the_pipe != INVALID_HANDLE_VALUE) - break; - - if (GetLastError() != ERROR_PIPE_BUSY) { - WINE_WARN("Unable to open named pipe %s (assuming unavailable).\n", - wine_dbgstr_a(NAME_RPCSS_NAMED_PIPE)); - break; - } - - WINE_WARN("Named pipe busy (will wait)\n"); - - if (!ReleaseMutex(master_mutex)) - WINE_ERR("Failed to release master mutex. Expect deadlock.\n"); - - /* wait for the named pipe. We are only - willing to wait only 5 seconds. It should be available /very/ soon. */ - if (! WaitNamedPipeA(NAME_RPCSS_NAMED_PIPE, MASTER_MUTEX_WAITNAMEDPIPE_TIMEOUT)) - { - WINE_ERR("Named pipe unavailable after waiting. Something is probably wrong.\n"); - return NULL; - } - - } - - if (the_pipe != INVALID_HANDLE_VALUE) { - dwmode = PIPE_READMODE_MESSAGE; - /* SetNamedPipeHandleState not implemented ATM, but still seems to work somehow. */ - if (! SetNamedPipeHandleState(the_pipe, &dwmode, NULL, NULL)) - WINE_WARN("Failed to set pipe handle state\n"); - } - - if (!ReleaseMutex(master_mutex)) - WINE_ERR("Uh oh, failed to leave the RPC Master Mutex!\n"); - - return the_pipe; -} - -static BOOL RPCSS_SendReceiveNPMsg(HANDLE np, PRPCSS_NP_MESSAGE msg, PRPCSS_NP_REPLY reply) -{ - DWORD count; - - WINE_TRACE("(np == %p, msg == %p, reply == %p)\n", np, msg, reply); - - if (! WriteFile(np, msg, sizeof(RPCSS_NP_MESSAGE), &count, NULL)) { - WINE_ERR("write failed.\n"); - return FALSE; - } - - if (count != sizeof(RPCSS_NP_MESSAGE)) { - WINE_ERR("write count mismatch.\n"); - return FALSE; - } - - if (! ReadFile(np, reply, sizeof(RPCSS_NP_REPLY), &count, NULL)) { - WINE_ERR("read failed.\n"); - return FALSE; - } - - if (count != sizeof(RPCSS_NP_REPLY)) { - WINE_ERR("read count mismatch, got %d.\n", count); - return FALSE; - } - - /* message execution was successful */ - return TRUE; -} - -BOOL RPCSS_BecomePipeServer(void) -{ - RPCSS_NP_MESSAGE msg; - RPCSS_NP_REPLY reply; - BOOL rslt = TRUE; - HANDLE client_handle, hthread, master_mutex = RPCSS_GetMasterMutex(); - DWORD threadid, wait_result; - - WINE_TRACE("\n"); - - wait_result = WaitForSingleObject(master_mutex, MASTER_MUTEX_TIMEOUT); - - switch (wait_result) { - case WAIT_ABANDONED: /* ? */ - case WAIT_OBJECT_0: - /* we have ownership */ - break; - case WAIT_FAILED: - case WAIT_TIMEOUT: - default: - WINE_ERR("Couldn't enter master mutex.\n"); - return FALSE; - } - - /* now we have the master mutex. during this time we will - * - * o check if an rpcss already listens on the pipe. If so, - * we will tell it we were invoked, which will cause the - * other end to update its timeouts. After, we just return - * false. - * - * o otherwise, we establish the pipe for ourselves and get - * ready to listen on it - */ - - if ((client_handle = RPCSS_NPConnect()) != INVALID_HANDLE_VALUE) { - ZeroMemory(&msg, sizeof(msg)); - msg.message_type = RPCSS_NP_MESSAGE_TYPEID_RANMSG; - msg.message.ranmsg.timeout = 1000; - msg.vardata_payload_size = 0; - if (!RPCSS_SendReceiveNPMsg(client_handle, &msg, &reply)) - WINE_ERR("Something is amiss: RPC_SendReceive failed.\n"); - CloseHandle(client_handle); - rslt = FALSE; - } - if (rslt) { - np_server_work_event = CreateEventA(NULL, FALSE, FALSE, "RpcNpServerWorkEvent"); - if (np_server_work_event == NULL) { - /* dunno what we can do then */ - WINE_ERR("Unable to create the np_server_work_event\n"); - assert(FALSE); - } - InitializeCriticalSection(&np_server_cs); - - np_server_end = CreateNamedPipe( - NAME_RPCSS_NAMED_PIPE, /* pipe name */ - PIPE_ACCESS_DUPLEX, /* pipe open mode */ - PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, /* pipe-specific modes */ - PIPE_UNLIMITED_INSTANCES, /* maximum number of instances */ - sizeof(RPCSS_NP_REPLY), /* output buffer size */ - sizeof(RPCSS_NP_MESSAGE), /* input buffer size */ - 2000, /* time-out interval */ - NULL /* SD */ - ); - - if (np_server_end == INVALID_HANDLE_VALUE) { - WINE_ERR("Failed to create named pipe!\n"); - DeleteCriticalSection(&np_server_cs); - if (!CloseHandle(np_server_work_event)) /* we will leak the handle... */ - WINE_WARN("Failed to close np_server_work_event handle!\n"); - np_server_work_event = NULL; - np_server_end = NULL; - rslt = FALSE; - } - } - - server_live = rslt; - - if (rslt) { - /* OK, now spawn the (single) server thread */ - hthread = CreateThread( - NULL, /* no security attribute */ - 0, /* default stack size */ - NPMainWorkThread, - NULL, /* thread parameter */ - 0, /* not suspended */ - &threadid /* returns thread ID (not used) */ - ); - if (hthread) { - WINE_TRACE("Created server thread.\n"); - CloseHandle(hthread); - } else { - WINE_ERR("Serious error: unable to create server thread!\n"); - if (!CloseHandle(np_server_work_event)) /* we will leak the handle... */ - WINE_WARN("Failed to close np_server_work_event handle!\n"); - if (!CloseHandle(np_server_end)) /* we will leak the handle... */ - WINE_WARN("Unable to close named pipe handle!\n"); - DeleteCriticalSection(&np_server_cs); - np_server_end = NULL; - np_server_work_event = NULL; - rslt = FALSE; - server_live = FALSE; - } - } - if (!ReleaseMutex(master_mutex)) - WINE_ERR("Unable to leave master mutex!??\n"); - - return rslt; -} - -BOOL RPCSS_NPDoWork(HANDLE exit_handle) -{ - HANDLE handles[2]; - DWORD waitresult; - - handles[0] = np_server_work_event; - handles[1] = exit_handle; - waitresult = WaitForMultipleObjects(2, handles, FALSE, INFINITE); - - if (waitresult == WAIT_OBJECT_0) - return TRUE; - - return FALSE; -} diff --git a/programs/rpcss/rpcss.h b/programs/rpcss/rpcss.h index b388a4d6085..9c2f04f7b86 100644 --- a/programs/rpcss/rpcss.h +++ b/programs/rpcss/rpcss.h @@ -21,28 +21,6 @@ #ifndef __WINE_RPCSS_H #define __WINE_RPCSS_H -#include "wine/rpcss_shared.h" #include "windows.h" -/* in seconds */ -#define RPCSS_DEFAULT_MAX_LAZY_TIMEOUT 30 - -/* rpcss_main.c */ -HANDLE RPCSS_GetMasterMutex(void); - -/* epmap_server.c */ -BOOL RPCSS_EpmapEmpty(void); -BOOL RPCSS_NPDoWork(HANDLE exit_event); -void RPCSS_RegisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count, - int binding_count, int no_replace, char *vardata, long vardata_size); -void RPCSS_UnregisterRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, int object_count, - int binding_count, char *vardata, long vardata_size); -void RPCSS_ResolveRpcEndpoints(RPC_SYNTAX_IDENTIFIER iface, UUID object, - char *protseq, char *rslt_ep); - -/* named_pipe_kludge.c */ -BOOL RPCSS_BecomePipeServer(void); -BOOL RPCSS_UnBecomePipeServer(void); -LONG RPCSS_SrvThreadCount(void); - #endif /* __WINE_RPCSS_H */ diff --git a/programs/rpcss/rpcss_main.c b/programs/rpcss/rpcss_main.c index 99b2d001502..1722d5eaebd 100644 --- a/programs/rpcss/rpcss_main.c +++ b/programs/rpcss/rpcss_main.c @@ -35,22 +35,12 @@ * these, also implement net.exe, at least for "net start" and * "net stop" (should be pretty easy I guess, assuming the rest * of the services API infrastructure works. - * - * o Is supposed to use RPC, not random kludges, to map endpoints. - * - * o Probably name services should be implemented here as well. - * - * o Wine's named pipes (in general) may not interoperate with those of - * Windows yet (?) * * o There is a looming problem regarding listening on privileged * ports. We will need to be able to coexist with SAMBA, and be able * to function without running winelib code as root. This may * take some doing, including significant reconceptualization of the * role of rpcss.exe in wine. - * - * o Who knows? Whatever rpcss does, we ought to at - * least think about doing... but what /does/ it do? */ #include @@ -62,76 +52,66 @@ #include "rpcss.h" #include "winnt.h" #include "irot.h" +#include "epm.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); -static HANDLE master_mutex; static HANDLE exit_event; extern HANDLE __wine_make_process_system(void); -HANDLE RPCSS_GetMasterMutex(void) -{ - return master_mutex; -} - -static BOOL RPCSS_work(HANDLE exit_event) -{ - return RPCSS_NPDoWork(exit_event); -} - static BOOL RPCSS_Initialize(void) { static unsigned short irot_protseq[] = IROT_PROTSEQ; static unsigned short irot_endpoint[] = IROT_ENDPOINT; + static unsigned short epm_protseq[] = {'n','c','a','c','n','_','n','p',0}; + static unsigned short epm_endpoint[] = {'\\','p','i','p','e','\\','e','p','m','a','p','p','e','r',0}; RPC_STATUS status; WINE_TRACE("\n"); - exit_event = __wine_make_process_system(); - - master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME); - if (!master_mutex) { - WINE_ERR("Failed to create master mutex\n"); + status = RpcServerRegisterIf(epm_v3_0_s_ifspec, NULL, NULL); + if (status != RPC_S_OK) + return status; + status = RpcServerRegisterIf(Irot_v0_2_s_ifspec, NULL, NULL); + if (status != RPC_S_OK) + { + RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, FALSE); return FALSE; } - if (!RPCSS_BecomePipeServer()) { - WINE_WARN("Server already running: exiting.\n"); - - CloseHandle(master_mutex); - master_mutex = NULL; - - return FALSE; - } + status = RpcServerUseProtseqEpW(epm_protseq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, + epm_endpoint, NULL); + if (status != RPC_S_OK) + goto fail; status = RpcServerUseProtseqEpW(irot_protseq, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, irot_endpoint, NULL); - if (status == RPC_S_OK) - status = RpcServerRegisterIf(Irot_v0_2_s_ifspec, NULL, NULL); - if (status == RPC_S_OK) - status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); - else - RpcServerUnregisterIf(Irot_v0_2_s_ifspec, NULL, FALSE); - - return status == RPC_S_OK; + if (status != RPC_S_OK) + goto fail; + + status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); + if (status != RPC_S_OK) + goto fail; + + exit_event = __wine_make_process_system(); + + return TRUE; + +fail: + RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, FALSE); + RpcServerUnregisterIf(Irot_v0_2_s_ifspec, NULL, FALSE); + return FALSE; } /* returns false if we discover at the last moment that we aren't ready to terminate */ static BOOL RPCSS_Shutdown(void) { - if (!RPCSS_UnBecomePipeServer()) - return FALSE; - - if (!CloseHandle(master_mutex)) - WINE_WARN("Failed to release master mutex\n"); - - master_mutex = NULL; - RpcMgmtStopServerListening(NULL); + RpcServerUnregisterIf(epm_v3_0_s_ifspec, NULL, TRUE); RpcServerUnregisterIf(Irot_v0_2_s_ifspec, NULL, TRUE); CloseHandle(exit_event); @@ -139,24 +119,16 @@ static BOOL RPCSS_Shutdown(void) return TRUE; } -static void RPCSS_MainLoop(void) -{ - WINE_TRACE("\n"); - - while ( RPCSS_work(exit_event) ) - ; -} - int main( int argc, char **argv ) { /* * We are invoked as a standard executable; we act in a - * "lazy" manner. We open up our pipe, and hang around until we all - * user processes exit, and then silently terminate. + * "lazy" manner. We register our interfaces and endpoints, and hang around + * until we all user processes exit, and then silently terminate. */ if (RPCSS_Initialize()) { - RPCSS_MainLoop(); + WaitForSingleObject(exit_event, INFINITE); RPCSS_Shutdown(); } diff --git a/programs/taskmgr/Ru.rc b/programs/taskmgr/Ru.rc new file mode 100644 index 00000000000..0534f75a304 --- /dev/null +++ b/programs/taskmgr/Ru.rc @@ -0,0 +1,500 @@ +/* + * Task Manager (Russian resources) + * + * Copyright 2008 Vladimir Pankratov + * + * + * 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 + */ + +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT + +/* + Menu +*/ + +IDR_TASKMANAGER MENU DISCARDABLE +BEGIN + POPUP "&Ôàéë" + BEGIN + MENUITEM "&Íîâàÿ çàäà÷à (Âûïîëíèòü...)", ID_FILE_NEW + MENUITEM SEPARATOR + MENUITEM "&Çàâåðøåíèå äèñïåò÷åðà çàäà÷", ID_FILE_EXIT + END + POPUP "&Ïàðàìåòðû" + BEGIN + MENUITEM "Ïîâå&ðõ îñòàëüíûõ îêîí", ID_OPTIONS_ALWAYSONTOP + , CHECKED + MENUITEM "&Ñâîðà÷èâàòü ïîñëå îáðàùåíèÿ", ID_OPTIONS_MINIMIZEONUSE + , CHECKED + MENUITEM "Ñ&êðûâàòü ñâåðíóòîå", ID_OPTIONS_HIDEWHENMINIMIZED + , CHECKED + MENUITEM "&Îòîáðàæàòü 16-ðàçðÿäíûå ïðîãðàììû", ID_OPTIONS_SHOW16BITTASKS + , CHECKED + END + POPUP "&Âèä" + BEGIN + MENUITEM "&Îáíîâèòü", ID_VIEW_REFRESH + POPUP "&Ñêîðîñòü îáíîâëåíèÿ" + BEGIN + MENUITEM "&Âûñîêàÿ", ID_VIEW_UPDATESPEED_HIGH + MENUITEM "&Îáû÷íàÿ", ID_VIEW_UPDATESPEED_NORMAL + , CHECKED + MENUITEM "&Íèçêàÿ", ID_VIEW_UPDATESPEED_LOW + MENUITEM "&Ïðèîñòàíîâèòü", ID_VIEW_UPDATESPEED_PAUSED + + END + MENUITEM SEPARATOR + MENUITEM "&Êðóïíûå çíà÷êè", ID_VIEW_LARGE + MENUITEM "&Ìåëêèå çíà÷êè", ID_VIEW_SMALL + MENUITEM "&Òàáëèöà", ID_VIEW_DETAILS, CHECKED + MENUITEM "Â&ûáðàòü ñòîëáöû...", ID_VIEW_SELECTCOLUMNS + POPUP "&Çàãðóçêà ÖÏ" + BEGIN + MENUITEM "&Îäèí ãðàôèê íà âñå ÖÏ", ID_VIEW_CPUHISTORY_ONEGRAPHALL + + MENUITEM "&Ïî ãðàôèêó íà êàæäûé ÖÏ", ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU + , CHECKED + END + MENUITEM "&Âûâîä âðåìåíè ÿäðà", ID_VIEW_SHOWKERNELTIMES + END + POPUP "&Îêíà" + BEGIN + MENUITEM "Ñ&ëåâà íàïðàâî", ID_WINDOWS_TILEHORIZONTALLY + MENUITEM "Ñ&âåðõó âíèç", ID_WINDOWS_TILEVERTICALLY + MENUITEM "&Ñâåðíóòü", ID_WINDOWS_MINIMIZE + MENUITEM "&Ðàçâåðíóòü", ID_WINDOWS_MAXIMIZE + MENUITEM "&Êàñêàäîì", ID_WINDOWS_CASCADE + MENUITEM "&Íà ïåðåäíèé ïëàí", ID_WINDOWS_BRINGTOFRONT + END + POPUP "&Ñïðàâêà" + BEGIN + MENUITEM "&Âûçîâ ñïðàâêè", ID_HELP_TOPICS + MENUITEM SEPARATOR + MENUITEM "&Î ïðîãðàììå", ID_HELP_ABOUT + END +END + +IDR_WINDOWSMENU MENU DISCARDABLE +BEGIN + MENUITEM "Ñ&ëåâà íàïðàâî", ID_WINDOWS_TILEHORIZONTALLY + MENUITEM "Ñ&âåðõó âíèç", ID_WINDOWS_TILEVERTICALLY + MENUITEM "&Ñâåðíóòü", ID_WINDOWS_MINIMIZE + MENUITEM "&Ðàçâåðíóòü", ID_WINDOWS_MAXIMIZE + MENUITEM "&Êàñêàäîì", ID_WINDOWS_CASCADE + MENUITEM "&Íà ïåðåäíèé ïëàí", ID_WINDOWS_BRINGTOFRONT +END + +IDR_APPLICATION_PAGE_CONTEXT1 MENU DISCARDABLE +BEGIN + POPUP "DUMMY" + BEGIN + MENUITEM "&Íîâàÿ çàäà÷à (Âûïîëíèòü...)", ID_FILE_NEW + MENUITEM SEPARATOR + MENUITEM "&Êðóïíûå çíà÷êè", ID_VIEW_LARGE + MENUITEM "&Ìåëêèå çíà÷êè", ID_VIEW_SMALL + MENUITEM "&Òàáëèöà", ID_VIEW_DETAILS, CHECKED + END +END + +IDR_APPLICATION_PAGE_CONTEXT2 MENU DISCARDABLE +BEGIN + POPUP "DUMMY" + BEGIN + MENUITEM "&Ïåðåêëþ÷èòüñÿ", ID_APPLICATION_PAGE_SWITCHTO + MENUITEM "&Íà ïåðåäíèé ïëàí", ID_WINDOWS_BRINGTOFRONT + MENUITEM SEPARATOR + MENUITEM "Ñ&ëåâà íàïðàâî", ID_WINDOWS_TILEHORIZONTALLY + MENUITEM "Ñ&âåðõó âíèç", ID_WINDOWS_TILEVERTICALLY + MENUITEM "&Ñâåðíóòü", ID_WINDOWS_MINIMIZE + MENUITEM "&Ðàçâåðíóòü", ID_WINDOWS_MAXIMIZE + MENUITEM "&Êàñêàäîì", ID_WINDOWS_CASCADE + MENUITEM SEPARATOR + MENUITEM "Ñíÿòü &çàäà÷ó", ID_APPLICATION_PAGE_ENDTASK + MENUITEM "&Ïåðåéòè ê ïðîöåññàì", ID_APPLICATION_PAGE_GOTOPROCESS + END +END + +IDR_TRAY_POPUP MENU DISCARDABLE +BEGIN + POPUP "DUMMY" + BEGIN + MENUITEM "&Âîññòàíîâèòü", ID_RESTORE + MENUITEM "&Çàêðûòü", ID_FILE_EXIT + MENUITEM SEPARATOR + MENUITEM "Ïîâå&ðõ îñòàëüíûõ îêîí", ID_OPTIONS_ALWAYSONTOP + END +END + +IDR_PROCESS_PAGE_CONTEXT MENU DISCARDABLE +BEGIN + POPUP "DUMMY" + BEGIN + MENUITEM "&Çàâåðøèòü ïðîöåññ", ID_PROCESS_PAGE_ENDPROCESS + MENUITEM "Çàâåðøèòü &äåðåâî ïðîöåññîâ", ID_PROCESS_PAGE_ENDPROCESSTREE + + MENUITEM "&Îòëàäêà", ID_PROCESS_PAGE_DEBUG + MENUITEM SEPARATOR + POPUP "&Ïðèîðèòåò" + BEGIN + MENUITEM "&Ðåàëüíîãî âðåìåíè", ID_PROCESS_PAGE_SETPRIORITY_REALTIME + + MENUITEM "&Âûñîêèé", ID_PROCESS_PAGE_SETPRIORITY_HIGH + + MENUITEM "Â&ûøå ñðåäíåãî", ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL + + MENUITEM "&Ñðåäíèé", ID_PROCESS_PAGE_SETPRIORITY_NORMAL + + MENUITEM "Í&èæå ñðåäíåãî", ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL + + MENUITEM "&Íèçêèé", ID_PROCESS_PAGE_SETPRIORITY_LOW + + END + MENUITEM "Çàäàòü &ñîîòâåòñòâèå...", ID_PROCESS_PAGE_SETAFFINITY + MENUITEM "Ðåäàêòèðîâàòü &êàíàëû îòëàäêè...", ID_PROCESS_PAGE_DEBUGCHANNELS + END +END + +/* + Dialog +*/ + +IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Î ïðîãðàììå Äèñïåò÷åð çàäà÷ WINE" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Task Manager v1.0\nCopyright (C) 1999 - 2001\nby Brian Palmer (brianp@reactos.org)", + IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,53,28, + 122,26 + DEFPUSHBUTTON "OK",IDOK,183,189,44,14,WS_GROUP + ICON IDI_TASKMANAGER,IDC_STATIC,19,30,20,20 + EDITTEXT IDC_LICENSE_EDIT,53,63,174,107,ES_MULTILINE | + ES_READONLY | WS_VSCROLL +END + +IDD_TASKMGR_DIALOG DIALOG DISCARDABLE 0, 0, 264, 246 +STYLE DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | + WS_THICKFRAME +CAPTION "Äèñïåò÷åð çàäà÷" +MENU IDR_TASKMANAGER +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Tab1",IDC_TAB,"SysTabControl32",WS_TABSTOP,3,3,257,228 +END + +IDD_APPLICATION_PAGE DIALOG DISCARDABLE 0, 0, 247, 210 +STYLE DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "List2",IDC_APPLIST,"SysListView32",LVS_REPORT | + LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP,7,7,233,177 + PUSHBUTTON "&Íîâàÿ çàäà÷à...",IDC_NEWTASK,187,189,53,14 + PUSHBUTTON "Ï&åðåêëþ÷èòüñÿ",IDC_SWITCHTO,131,189,53,14,WS_DISABLED + PUSHBUTTON "Ñíÿòü &çàäà÷ó",IDC_ENDTASK,75,189,53,14,WS_DISABLED +END + +IDD_PROCESS_PAGE DIALOG DISCARDABLE 0, 0, 247, 210 +STYLE DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "List2",IDC_PROCESSLIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_OWNERDATA | + WS_BORDER | WS_TABSTOP,7,7,233,177 + PUSHBUTTON "&Çàâåðøèòü ïðîöåññ",IDC_ENDPROCESS,171,189,69,14 + CONTROL "&Îòîáðàæàòü ïðîöåññû âñåõ ïîëüçîâàòåëåé",IDC_SHOWALLPROCESSES, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,191,157,10 +END + +/*IDD_PERFORMANCE_PAGE DIALOGEX 0, 0, 247, 210*/ +IDD_PERFORMANCE_PAGE DIALOGEX DISCARDABLE 0, 0, 247, 210 +STYLE DS_CONTROL | WS_CHILD | WS_CLIPCHILDREN +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Çàãðóçêà ÖÏ",IDC_CPU_USAGE_FRAME,5,5,60,54,WS_TABSTOP, WS_EX_TRANSPARENT + GROUPBOX "Ôàéë ïîäêà÷êè",IDC_MEM_USAGE_FRAME,5,63,60,54,BS_LEFTTEXT, WS_EX_TRANSPARENT + GROUPBOX "Âñåãî",IDC_TOTALS_FRAME,5,122,111,39,0,WS_EX_TRANSPARENT + GROUPBOX "Âûäåëåíèå ïàìÿòè (ÊÁ)",IDC_COMMIT_CHARGE_FRAME,5,166,111,39,0,WS_EX_TRANSPARENT + GROUPBOX "Ôèçè÷åñêàÿ ïàìÿòü (ÊÁ)",IDC_PHYSICAL_MEMORY_FRAME,131,122,111,39,0,WS_EX_TRANSPARENT + GROUPBOX "Ïàìÿòü ÿäðà (ÊÁ)",IDC_KERNEL_MEMORY_FRAME,131,166,111,39,0,WS_EX_TRANSPARENT + LTEXT "Äåñêðèïòîðîâ",IDS_TOTALS_HANDLE_COUNT,12,131,80,8 + LTEXT "Ïîòîêîâ",IDS_TOTALS_THREAD_COUNT,12,140,27,8 + LTEXT "Ïðîöåññîâ",IDS_TOTALS_PROCESS_COUNT,12,149,35,8 + EDITTEXT IDC_TOTALS_HANDLE_COUNT,65,131,45,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + EDITTEXT IDC_TOTALS_THREAD_COUNT,65,140,45,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + EDITTEXT IDC_TOTALS_PROCESS_COUNT,65,149,45,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + LTEXT "Âñåãî",IDS_COMMIT_CHARGE_TOTAL,12,175,27,8 + LTEXT "Ïðåäåë",IDS_COMMIT_CHARGE_LIMIT,12,184,50,8 + LTEXT "Ïèê",IDS_COMMIT_CHARGE_PEAK,12,193,34,8 + EDITTEXT IDC_COMMIT_CHARGE_TOTAL,65,174,45,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + EDITTEXT IDC_COMMIT_CHARGE_LIMIT,65,184,45,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + EDITTEXT IDC_COMMIT_CHARGE_PEAK,65,193,45,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + LTEXT "Âñåãî",IDS_PHYSICAL_MEMORY_TOTAL,137,131,27,8 + LTEXT "Äîñòóïíî",IDS_PHYSICAL_MEMORY_AVAILABLE,137,140,31,8 + LTEXT "Ñèñòåìíûé êåø",IDS_PHYSICAL_MEMORY_SYSTEM_CACHE,137,149,46,8 + EDITTEXT IDC_PHYSICAL_MEMORY_TOTAL,185,131,48,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + EDITTEXT IDC_PHYSICAL_MEMORY_AVAILABLE,185,140,48,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + EDITTEXT IDC_PHYSICAL_MEMORY_SYSTEM_CACHE,185,149,48,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + LTEXT "Âñåãî",IDS_KERNEL_MEMORY_TOTAL,137,174,27,8 + LTEXT "Âûãðóæàåìàÿ",IDS_KERNEL_MEMORY_PAGED,137,184,70,8 + LTEXT "Íåâûãðóæ.",IDS_KERNEL_MEMORY_NONPAGED,137,193,70,8 + EDITTEXT IDC_KERNEL_MEMORY_TOTAL,185,174,48,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + EDITTEXT IDC_KERNEL_MEMORY_PAGED,185,184,48,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + EDITTEXT IDC_KERNEL_MEMORY_NONPAGED,185,193,48,8,ES_RIGHT | + ES_READONLY | ES_NUMBER | NOT WS_BORDER + GROUPBOX "Õðîíîëîãèÿ çàãðóçêè ÖÏ",IDC_CPU_USAGE_HISTORY_FRAME,74,5,168,54,0,WS_EX_TRANSPARENT + GROUPBOX "Õðîíîëîãèÿ èñïîëüçîâàíèÿ ôàéëà ïîäêà÷êè",IDC_MEMORY_USAGE_HISTORY_FRAME,74,63,168,54,0,WS_EX_TRANSPARENT + PUSHBUTTON "Õðîíîëîãèÿ çàãðóçêè ÖÏ",IDC_CPU_USAGE_GRAPH,12,17,47,37,0, + WS_EX_CLIENTEDGE + PUSHBUTTON "Ôàéë ïîäêà÷êè",IDC_MEM_USAGE_GRAPH,12,75,47,37,0, + WS_EX_CLIENTEDGE + PUSHBUTTON "Õðîíîëîãèÿ çàãðóçêè ÖÏ",IDC_CPU_USAGE_HISTORY_GRAPH,81,17, + 153,37,0,WS_EX_CLIENTEDGE + PUSHBUTTON "Ôàéë ïîäêà÷êè",IDC_MEM_USAGE_HISTORY_GRAPH,81,75, + 153,37,0,WS_EX_CLIENTEDGE +END + +IDD_DEBUG_CHANNELS_DIALOG DIALOG DISCARDABLE 0, 0, 247, 210 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Êàíàëû îòëàäêè" +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "List2",IDC_DEBUG_CHANNELS_LIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP | + LVS_SORTASCENDING,7,7,233,177 + PUSHBUTTON "Çàêðûòü",IDOK,171,189,69,14 +END + +IDD_AFFINITY_DIALOG DIALOG DISCARDABLE 0, 0, 231, 154 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Ñîîòâåòñòâèå ïðîöåññîðîâ" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "OK",IDOK,120,133,50,14 + PUSHBUTTON "Îòìåíà",IDCANCEL,174,133,50,14 + LTEXT "Ñîîòâåòñòâèå ïðîöåññîðîâ îïðåäåëÿåò, êàêîé ÖÏ ðàçðåøåíî èñïîëüçîâàòü ïðîöåññó.", + IDC_STATIC,5,5,220,16 + CONTROL "ÖÏ 0",IDC_CPU0,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, + 11,28,37,10 + CONTROL "ÖÏ 1",IDC_CPU1,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,11,41,37,10 + CONTROL "ÖÏ 2",IDC_CPU2,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,11,54,37,10 + CONTROL "ÖÏ 3",IDC_CPU3,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,11,67,37,10 + CONTROL "ÖÏ 4",IDC_CPU4,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,11,80,37,10 + CONTROL "ÖÏ 5",IDC_CPU5,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,11,93,37,10 + CONTROL "ÖÏ 6",IDC_CPU6,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,11,106,37,10 + CONTROL "ÖÏ 7",IDC_CPU7,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,11,119,37,10 + CONTROL "ÖÏ 8",IDC_CPU8,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,61,28,37,10 + CONTROL "ÖÏ 9",IDC_CPU9,"Button",BS_AUTOCHECKBOX | WS_DISABLED | + WS_TABSTOP,61,41,37,10 + CONTROL "ÖÏ 10",IDC_CPU10,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,61,54,41,10 + CONTROL "ÖÏ 11",IDC_CPU11,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,61,67,41,10 + CONTROL "ÖÏ 12",IDC_CPU12,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,61,80,41,10 + CONTROL "ÖÏ 13",IDC_CPU13,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,61,93,41,10 + CONTROL "ÖÏ 14",IDC_CPU14,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,61,106,41,10 + CONTROL "ÖÏ 15",IDC_CPU15,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,61,119,41,10 + CONTROL "ÖÏ 16",IDC_CPU16,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,116,28,41,10 + CONTROL "ÖÏ 17",IDC_CPU17,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,116,41,41,10 + CONTROL "ÖÏ 18",IDC_CPU18,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,116,54,41,10 + CONTROL "ÖÏ 19",IDC_CPU19,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,116,67,41,10 + CONTROL "ÖÏ 20",IDC_CPU20,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,116,80,41,10 + CONTROL "ÖÏ 21",IDC_CPU21,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,116,93,41,10 + CONTROL "ÖÏ 22",IDC_CPU22,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,116,106,41,10 + CONTROL "ÖÏ 23",IDC_CPU23,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,116,119,41,10 + CONTROL "ÖÏ 24",IDC_CPU24,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,175,28,41,10 + CONTROL "ÖÏ 25",IDC_CPU25,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,175,41,41,10 + CONTROL "ÖÏ 26",IDC_CPU26,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,175,54,41,10 + CONTROL "ÖÏ 27",IDC_CPU27,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,175,67,41,10 + CONTROL "ÖÏ 28",IDC_CPU28,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,175,80,41,10 + CONTROL "ÖÏ 29",IDC_CPU29,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,175,93,41,10 + CONTROL "ÖÏ 30",IDC_CPU30,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,175,106,41,10 + CONTROL "ÖÏ 31",IDC_CPU31,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,175,119,41,10 +END + +IDD_COLUMNS_DIALOG DIALOG DISCARDABLE 0, 0, 195, 199 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Âûáîð ñòîëáöîâ" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "OK",IDOK,84,178,50,14 + PUSHBUTTON "Îòìåíà",IDCANCEL,138,178,50,14 + LTEXT "Âûáåðèòå ñòîëáöû, êîòîðûå ïîÿâÿòñÿ íà ñòðàíèöå ïðîöåññîâ äèñïåò÷åðà çàäà÷.", + IDC_STATIC,7,7,181,17 + CONTROL "&Èìÿ îáðàçà",IDC_IMAGENAME,"Button",BS_AUTOCHECKBOX | + WS_DISABLED | WS_TABSTOP,7,28,56,10 + CONTROL "Èäåíòè&ô. ïðîöåññà (PID)",IDC_PID,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,39,88,10 + CONTROL "&Çàãðóçêà ÖÏ",IDC_CPUUSAGE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,7,50,53,10 + CONTROL "&Âðåìÿ ÖÏ",IDC_CPUTIME,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,7,61,48,10 + CONTROL "&Ïàìÿòü - èñïîëüçîâàíèå",IDC_MEMORYUSAGE,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,7,72,63,10 + CONTROL "Ïàìÿòü - èçìå&íåíèå",IDC_MEMORYUSAGEDELTA,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,83,82,10 + CONTROL "Ïàìÿòü - &ìàêñèìóì",IDC_PEAKMEMORYUSAGE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,94,82,10 + CONTROL "&Îøèáîê ñòðàíèöû",IDC_PAGEFAULTS,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,7,105,53,10 + CONTROL "Îá&úåêòû USER",IDC_USEROBJECTS,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,7,116,62,10 + CONTROL "×èñëî ÷òåíèé",IDC_IOREADS,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,7,127,49,10 + CONTROL "Ïðî÷èòàíî áàéò",IDC_IOREADBYTES,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,7,138,65,10 + CONTROL "Êîä ñå&àíñà",IDC_SESSIONID,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,7,149,50,10 + CONTROL "Èì&ÿ ïîëüçîâàòåëÿ",IDC_USERNAME,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,7,160,51,10 + CONTROL "Îøèáîê &ñòðàíèöû - èçìåíåíèå",IDC_PAGEFAULTSDELTA,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,107,28,72,10 + CONTROL "Îáúåì âèðòó&àëüíîé ïàìÿòè",IDC_VIRTUALMEMORYSIZE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,107,39,77,10 + CONTROL "Âû&ãðóæàåìûé ïóë",IDC_PAGEDPOOL,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,107,50,53,10 + CONTROL "Íåâûãðóæàåìûé ï&óë",IDC_NONPAGEDPOOL,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,107,61,67,10 + CONTROL "&Áàçîâûé ïðèîðèòåò",IDC_BASEPRIORITY,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,107,72,55,10 + CONTROL "Ñ÷åò÷èê &äåñêðèïòîðîâ",IDC_HANDLECOUNT,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,107,83,59,10 + CONTROL "Ñ&÷åò÷èê ïîòîêîâ",IDC_THREADCOUNT,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,107,94,59,10 + CONTROL "Îáú&åêòû GDI",IDC_GDIOBJECTS,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,107,105,55,10 + CONTROL "×èñëî çàïèñåé",IDC_IOWRITES,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,107,116,49,10 + CONTROL "Çàïèñàíî áàéò",IDC_IOWRITEBYTES,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,107,127,65,10 + CONTROL "Ïðî÷èé ââîä-âûâîä",IDC_IOOTHER,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,107,138,46,10 + CONTROL "Ïðî÷èõ áàéò ïðè ââîäå-âûâîäå",IDC_IOOTHERBYTES,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,107,149,65,10 +END + +/* + String Table +*/ + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APP_TITLE "Äèñïåò÷åð çàäà÷" + IDC_TASKMGR "Äèñïåò÷åð çàäà÷" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_FILE_NEW "Çàïóñêàåò íîâóþ ïðîãðàììó" + ID_OPTIONS_ALWAYSONTOP "Îêíî Äèñïåò÷åðà çàäà÷ îòîáðàæàåòñÿ ïîâåðõ äðóãèõ îêîí, åñëè íå ñâåðíóòî" + ID_OPTIONS_MINIMIZEONUSE + "Îêíî Äèñïåò÷åðà çàäà÷ ñâåðòûâàåòñÿ ïðè âûïîëíåíèè ïåðåêëþ÷åíèÿ" + ID_OPTIONS_HIDEWHENMINIMIZED "Ñêðûâàåò ñâåðíóòîå îêíî Äèñïåò÷åðà çàäà÷" + ID_VIEW_REFRESH "Âûçûâàåò íåìåäëåííîå îáíîâëåíèå îêíà Äèñïåò÷åðà çàäà÷" + ID_VIEW_LARGE "Îòîáðàæàåò çàäà÷è â âèäå êðóïíûõ çíà÷êîâ" + ID_VIEW_SMALL "Îòîáðàæàåò çàäà÷è â âèäå ìåëêèõ çíà÷êîâ" + ID_VIEW_DETAILS "Îòîáðàæàåò äîïîëíèòåëüíóþ èíôîðìàöèþ î çàäà÷àõ" + ID_VIEW_UPDATESPEED_HIGH "Îáíîâëÿåò èçîáðàæåíèå äâà ðàçà â ñåêóíäó" + ID_VIEW_UPDATESPEED_NORMAL "Îáíîâëÿåò èçîáðàæåíèå îäèí ðàç â äâå ñåêóíäû" + ID_VIEW_UPDATESPEED_LOW "Îáíîâëÿåò èçîáðàæåíèå îäèí ðàç â ÷åòûðå ñåêóíäû" +END + +STRINGTABLE DISCARDABLE +BEGIN +ID_VIEW_UPDATESPEED_PAUSED "Èçîáðàæåíèå íå îáíîâëÿåòñÿ àâòîìàòè÷åñêè" + ID_WINDOWS_TILEHORIZONTALLY + "Ðàçìåùàåò âûáðàííûå îêíà ñëåâà íàïðàâî" + ID_WINDOWS_TILEVERTICALLY "Ðàçìåùàåò âûáðàííûå îêíà îäíî íàä äðóãèì" + ID_WINDOWS_MINIMIZE "Ñâåðòûâàåò îêíà âûáðàííûõ çàäà÷" + ID_WINDOWS_MAXIMIZE "Ðàçâåðòûâàåò îêíà íà âåñü ðàáî÷èé ñòîë" + ID_WINDOWS_CASCADE "Ðàçìåùàåò âûáðàííûå îêíà êàñêàäîì" + ID_WINDOWS_BRINGTOFRONT "Ïåðåìåùàåò îêíî íà ïåðåäíèé ïëàí, íî íå àêòèâèçèðóåò åãî" + ID_HELP_TOPICS "Îòêðûâàåò îêíî âñòðîåííîé ñïðàâêè Äèñïåò÷åðà çàäà÷" + ID_HELP_ABOUT "Âûâîä ñâåäåíèé î ïðîãðàììå, åå âåðñèè è àâòîðñêèõ ïðàâàõ" + ID_FILE_EXIT "Çàâåðøàåò Äèñïåò÷åð çàäà÷" + ID_OPTIONS_SHOW16BITTASKS + "Îòîáðàæàåò 16-ðàçðÿäíûå çàäà÷è, îáðàáàòûâàåìûå ntvdm.exe" + ID_VIEW_SELECTCOLUMNS "Îïðåäåëÿåò ñïèñîê ñòîëáöîâ, îòîáðàæàåìûõ íà âêëàäêå Ïðîöåññû" + ID_VIEW_SHOWKERNELTIMES "Îòîáðàæàåò âðåìÿ ÿäðà íà ãðàôèêàõ çàãðóæåííîñòè" + ID_VIEW_CPUHISTORY_ONEGRAPHALL + "Îäèí õðîíîëîãè÷åñêèé ãðàôèê îáùåé çàãðóçêè ÖÏ" + ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU "Êàæäîìó ÖÏ ñîîòâåòñòâóåò ñâîé ãðàôèê" + ID_APPLICATION_PAGE_SWITCHTO + "Ïåðåìåùàåò çàäà÷è íà ïåðåäíèé ïëàí è ïåðåäàåò èì óïðàâëåíèå" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_ENDTASK "Çàâåðøàåò âûáðàííûé ïðîöåññ" + ID_GOTOPROCESS "Ïåðåêëþ÷àåò ôîêóñ íà ïðîöåññ âûáðàííîé çàäà÷è" + ID_RESTORE "Âîññòàíàâëèâàåò ñêðûòîå îêíî Äèñïåò÷åðà çàäà÷" + ID_PROCESS_PAGE_ENDPROCESS "Óäàëÿåò ïðîöåññ èç ñèñòåìû" + ID_PROCESS_PAGE_ENDPROCESSTREE + "Óäàëÿåò èç ñèñòåìû ýòîò ïðîöåññ è âñåõ åãî ïîòîìêîâ." + ID_PROCESS_PAGE_DEBUG "Ïðèìåíÿåò îòëàä÷èê ê ýòîìó ïðîöåññó" + ID_PROCESS_PAGE_SETAFFINITY + "Óñòàíàâëèâàåò, êàêèå ÖÏ ìîæåò èñïîëüçîâàòü ïðîöåññ" + ID_PROCESS_PAGE_SETPRIORITY_REALTIME + "Óñòàíàâëèâàåò êëàññ ïðèîðèòåòà ÐÅÀËÜÍÎÃÎ ÂÐÅÌÅÍÈ äëÿ ïðîöåññà" + ID_PROCESS_PAGE_SETPRIORITY_HIGH "Óñòàíàâëèâàåò êëàññ ïðèîðèòåòà ÂÛÑÎÊÈÉ äëÿ ïðîöåññà" + ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL + "Óñòàíàâëèâàåò êëàññ ïðèîðèòåòà ÂÛØÅ ÑÐÅÄÍÅÃÎ äëÿ ïðîöåññà" + ID_PROCESS_PAGE_SETPRIORITY_NORMAL + "Óñòàíàâëèâàåò êëàññ ïðèîðèòåòà ÑÐÅÄÍÈÉ äëÿ ïðîöåññà" + ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL + "Óñòàíàâëèâàåò êëàññ ïðèîðèòåòà ÍÈÆÅ ÑÐÅÄÍÅÃÎ äëÿ ïðîöåññà" + ID_PROCESS_PAGE_SETPRIORITY_LOW "Óñòàíàâëèâàåò êëàññ ïðèîðèòåòà ÍÈÇÊÈÉ äëÿ ïðîöåññà" + IDS_LICENSE "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.\r\n\r\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r\n\r\nYou should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA." +END diff --git a/programs/taskmgr/taskmgr.rc b/programs/taskmgr/taskmgr.rc index 3f80e52e5f5..5cd228efbab 100644 --- a/programs/taskmgr/taskmgr.rc +++ b/programs/taskmgr/taskmgr.rc @@ -36,6 +36,7 @@ #include "Nl.rc" #include "No.rc" #include "Pl.rc" +#include "Ru.rc" #include "Si.rc" #include "Tr.rc" diff --git a/programs/winecfg/Bg.rc b/programs/winecfg/Bg.rc index 5a42f2406ba..ea1f9fa0d9a 100644 --- a/programs/winecfg/Bg.rc +++ b/programs/winecfg/Bg.rc @@ -42,6 +42,11 @@ BEGIN */ LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Cs.rc b/programs/winecfg/Cs.rc index b6e988858df..81e6ce2f73b 100644 --- a/programs/winecfg/Cs.rc +++ b/programs/winecfg/Cs.rc @@ -44,6 +44,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Da.rc b/programs/winecfg/Da.rc index 84867c19be4..d64361ac437 100644 --- a/programs/winecfg/Da.rc +++ b/programs/winecfg/Da.rc @@ -39,6 +39,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "Dette bibliotek er fri software; du må re-distribuere det og/eller modificere det under betingelserne givet i GNU Lesser General Public License som publiceret af Free Software Foundation; enten version 2.1, eller (efter dit valg) en senere version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows registreringsoplysninger ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Ejer:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organisationen:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/De.rc b/programs/winecfg/De.rc index fa67d435d83..4e80c4dbfa3 100644 --- a/programs/winecfg/De.rc +++ b/programs/winecfg/De.rc @@ -39,6 +39,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "Diese Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der GNU Lesser General Public License, wie von der Free Software Foundation veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows-Registrierungs-Informationen ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Eigentümer:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organisation:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/En.rc b/programs/winecfg/En.rc index afcb47ff2d5..1a07d71ff6a 100644 --- a/programs/winecfg/En.rc +++ b/programs/winecfg/En.rc @@ -41,6 +41,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Es.rc b/programs/winecfg/Es.rc index 29fdccd0c45..01f9c70ead9 100644 --- a/programs/winecfg/Es.rc +++ b/programs/winecfg/Es.rc @@ -39,6 +39,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Información de Registro de Windows ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Propietario:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organización:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Fi.rc b/programs/winecfg/Fi.rc index 19981ebde8b..fb1a41faf43 100644 --- a/programs/winecfg/Fi.rc +++ b/programs/winecfg/Fi.rc @@ -40,6 +40,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Omistaja:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organisaatio:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Fr.rc b/programs/winecfg/Fr.rc index ee8cd9fa151..36902ba6b09 100644 --- a/programs/winecfg/Fr.rc +++ b/programs/winecfg/Fr.rc @@ -39,6 +39,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier suivant les termes de la Licence Générale Publique Limitée, telle que publiée par la Free Software Foundation ; soit la version 2.1 de la License, soit (à votre gré) toute version ultérieure." IDC_STATIC,119,44,124,72 + GROUPBOX " Les renseignements pour l'inscription Windows ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Propriétaire:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organisation:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Hu.rc b/programs/winecfg/Hu.rc index 87f52bf2963..360d277c197 100644 --- a/programs/winecfg/Hu.rc +++ b/programs/winecfg/Hu.rc @@ -39,6 +39,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "Ez a függvénykönvtár szabad szoftver; szabadon terjesztheti, vagy módosíthatja a GNU Lesser General Public Liszenc feltételei szerint, amit a Free Software Foundation készített; mind a 2.1 verziójú licensz, vagy (választása szerint) bármely késõbbi verzió használható.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/It.rc b/programs/winecfg/It.rc index 0400b655fb5..337da946b4f 100644 --- a/programs/winecfg/It.rc +++ b/programs/winecfg/It.rc @@ -31,6 +31,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows informazioni di registrazione ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Proprietario:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organizzazione:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Ja.rc b/programs/winecfg/Ja.rc index 82380ca538b..ff111ee596c 100644 --- a/programs/winecfg/Ja.rc +++ b/programs/winecfg/Ja.rc @@ -41,6 +41,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Ko.rc b/programs/winecfg/Ko.rc index 578cc4111a3..75c24c5815e 100644 --- a/programs/winecfg/Ko.rc +++ b/programs/winecfg/Ko.rc @@ -42,6 +42,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "ÀÌ ¶óÀ̺귯¸®´Â ÀÚÀ¯ ¼ÒÇÁÆ®¿þ¾îÀÔ´Ï´Ù. ´ç½ÅÀº ÀÚÀ¯ ¼ÒÇÁÆ®¿þ¾î Àç´Ü(Free Software Foundation)¿¡¼­ ¸¸µç GNU LGPL(Lesser General Public License) ¾Æ·¡¿¡¼­ ÀÌ ÇÁ·Î±×·¥À» Àç¹èÆ÷ ¶Ç´Â ¼öÁ¤ÇÒ ¼ö ÀÖ½À´Ï´Ù. ¶óÀ̼¾½ºÀÇ ¹öÀüÀº 2.1 ¶Ç´Â (¼±ÅÃÀûÀ¸·Î) ±× ÀÌÈÄ ¹öÀüÀ» µû¸£¸é µË´Ï´Ù.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Nl.rc b/programs/winecfg/Nl.rc index 10620d125f6..6259fff97e3 100644 --- a/programs/winecfg/Nl.rc +++ b/programs/winecfg/Nl.rc @@ -41,6 +41,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,124,8 LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows registratie-informatie ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Eigenaar:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organisatie:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/No.rc b/programs/winecfg/No.rc index d155caee12c..f31d05de4a2 100644 --- a/programs/winecfg/No.rc +++ b/programs/winecfg/No.rc @@ -39,6 +39,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "Dette biblioteket er fri programvarer; det kan redistribueres i henhold til vilkårene i GNU Lesser General Public License utgitt av «the Free Software Foundation», enten versjon 2.1 av denne Lisensen, eller (hvis du ønsker det) en nyere versjon.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Påmelding Informasjon ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Eier:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organisasjon:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Pl.rc b/programs/winecfg/Pl.rc index 794010d1640..7e7d98574e0 100644 --- a/programs/winecfg/Pl.rc +++ b/programs/winecfg/Pl.rc @@ -42,6 +42,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "Ta biblioteka jest wolnym oprogramowaniem; mo¿esz j¹ rozpowszechniaæ i/lub modyfikowaæ pod warunkami licencji GNU Lesser General Public License opublikowanej przez Free Software Foundation; licencji w wersji 2.1, lub (wed³ug w³asnego uznania) dowolnej póŸniejszej.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Pt.rc b/programs/winecfg/Pt.rc index 1a701051d93..68fc52a43f4 100644 --- a/programs/winecfg/Pt.rc +++ b/programs/winecfg/Pt.rc @@ -43,6 +43,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Informações de registro do Windows ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Proprietário:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organização:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE @@ -56,6 +61,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "Esta biblioteca é de código livre; pode-a redistribuir e/ou modificar nos termos da Licença Publica Geral Lesser GNU como publicado pela Fundação de Programas Livres; também a versão 2.1 da Licença, ou (na sua opinião) qualquer versão posterior.", IDC_STATIC,119,44,124,72 + GROUPBOX " Informações de registro do Windows ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Proprietário:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organização:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END diff --git a/programs/winecfg/Ro.rc b/programs/winecfg/Ro.rc index 79f7f89d461..9fb47120f45 100644 --- a/programs/winecfg/Ro.rc +++ b/programs/winecfg/Ro.rc @@ -41,6 +41,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Ru.rc b/programs/winecfg/Ru.rc index 7315e95107e..7b23136c62f 100644 --- a/programs/winecfg/Ru.rc +++ b/programs/winecfg/Ru.rc @@ -43,6 +43,11 @@ BEGIN */ LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Si.rc b/programs/winecfg/Si.rc index 01ab2f6f9d9..8a8b5efff7a 100644 --- a/programs/winecfg/Si.rc +++ b/programs/winecfg/Si.rc @@ -41,6 +41,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Sv.rc b/programs/winecfg/Sv.rc index 50a994e1c7b..768d830de72 100644 --- a/programs/winecfg/Sv.rc +++ b/programs/winecfg/Sv.rc @@ -39,6 +39,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "Detta bibliotek är fri programvara. Du kan distribuera det och/eller modifiera det under villkoren i GNU Lesser General Public License, publicerad av Free Software Foundation, antingen version 2.1 eller (om du så vill) någon senare version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Tr.rc b/programs/winecfg/Tr.rc index 71ce170b9cc..45885c1ed9b 100644 --- a/programs/winecfg/Tr.rc +++ b/programs/winecfg/Tr.rc @@ -39,6 +39,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/Zh.rc b/programs/winecfg/Zh.rc index 209340081ef..816c94c898b 100644 --- a/programs/winecfg/Zh.rc +++ b/programs/winecfg/Zh.rc @@ -39,6 +39,11 @@ BEGIN LTEXT "http://www.winehq.org/",IDC_STATIC,119,31,106,8 LTEXT "³o¤@¨ç¦¡®w¬O¦Û¥Ñ³nÅé¡A §A¥i¥H¿í·Ó¦Û¥Ñ³nÅé°òª÷·|¥Xª©ªº GNU ¸û¼eÃP³q¥Î¤½¦@³\\¥iÃÒ±ø´Ú ¨Ó­×§ï©M­«·sµo§G³o¤@µ{¦¡¡A ©ÎªÌ¬O³\\¥iÃÒªº2.1ª©¡A ©Î¬O (®Ú¾Ú§Aªº¿ï¾Ü) ¥ô¦ó§ó·sªºª©¥»¡C", IDC_STATIC,119,44,124,72 + GROUPBOX " Windows Registration Information ", IDC_STATIC, 15, 110, 230, 55 + LTEXT "Owner:", IDC_STATIC, 22, 126, 40, 20 + LTEXT "Organization:", IDC_STATIC, 22, 140, 50, 20 + EDITTEXT IDC_ABT_OWNER, 75, 126, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP + EDITTEXT IDC_ABT_ORG, 75, 140, 160, 13, ES_AUTOHSCROLL | WS_TABSTOP END IDD_APPCFG DIALOG DISCARDABLE 0, 0, 260, 250 diff --git a/programs/winecfg/main.c b/programs/winecfg/main.c index f9f561dbe87..e363bb74870 100644 --- a/programs/winecfg/main.c +++ b/programs/winecfg/main.c @@ -59,20 +59,59 @@ PropSheetCallback (HWND hWnd, UINT uMsg, LPARAM lParam) static INT_PTR CALLBACK AboutDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + char *owner, *org; + switch (uMsg) { case WM_NOTIFY: - if (((LPNMHDR)lParam)->code != PSN_SETACTIVE) break; - /* otherwise fall through, we want to refresh the page as well */ - case WM_INITDIALOG: - break; + switch(((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + /*save registration info to registry */ + owner = get_text(hDlg, IDC_ABT_OWNER); + org = get_text(hDlg, IDC_ABT_ORG); + + set_reg_key(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", + "RegisteredOwner", owner ? owner : ""); + set_reg_key(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", + "RegisteredOrganization", org ? org : ""); + set_reg_key(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion", + "RegisteredOwner", owner ? owner : ""); + set_reg_key(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion", + "RegisteredOrganization", org ? org : ""); + apply(); + + HeapFree(GetProcessHeap(), 0, owner); + HeapFree(GetProcessHeap(), 0, org); + break; + } + break; + + case WM_INITDIALOG: + /* read owner and organization info from registry, load it into text box */ + owner = get_reg_key(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion", + "RegisteredOwner", ""); + org = get_reg_key(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT\\CurrentVersion", + "RegisteredOrganization", ""); + + SetDlgItemText(hDlg, IDC_ABT_OWNER, owner); + SetDlgItemText(hDlg, IDC_ABT_ORG, org); + + SendMessage(GetParent(hDlg), PSM_UNCHANGED, 0, 0); + + HeapFree(GetProcessHeap(), 0, owner); + HeapFree(GetProcessHeap(), 0, org); + break; case WM_COMMAND: - break; - - default: - break; - + switch(HIWORD(wParam)) + { + case EN_CHANGE: + /* enable apply button */ + SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0); + break; + } + break; } return FALSE; } diff --git a/programs/winecfg/resource.h b/programs/winecfg/resource.h index 2ce1ab9437e..2182c297462 100644 --- a/programs/winecfg/resource.h +++ b/programs/winecfg/resource.h @@ -249,3 +249,7 @@ #define IDC_SYSPARAMS_INACTIVE_TITLE_GRADIENT 8429 #define IDC_SYSPARAMS_MENU_HILIGHT 8430 #define IDC_SYSPARAMS_MENUBAR 8431 + +/* About tab */ +#define IDC_ABT_OWNER 8432 +#define IDC_ABT_ORG 8433 diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c index d334d17f46d..5fba6faab2f 100644 --- a/programs/winedbg/tgt_active.c +++ b/programs/winedbg/tgt_active.c @@ -380,10 +380,10 @@ static DWORD dbg_handle_exception(const EXCEPTION_RECORD* rec, BOOL first_chance dbg_printf("invalid float operation"); break; case EXCEPTION_FLT_OVERFLOW: - dbg_printf("floating pointer overflow"); + dbg_printf("floating point overflow"); break; case EXCEPTION_FLT_UNDERFLOW: - dbg_printf("floating pointer underflow"); + dbg_printf("floating point underflow"); break; case EXCEPTION_FLT_STACK_CHECK: dbg_printf("floating point stack check"); diff --git a/programs/winemine/README b/programs/winemine/README index e3649357709..711b5f9c1e3 100644 --- a/programs/winemine/README +++ b/programs/winemine/README @@ -8,9 +8,6 @@ This is minesweeper for wine... Enjoy. I wrote it because it rhymes ;). KNOWN BUGS: - Chokes on fastest times names greater than 16 characters long, must have - something to do with GetDlgItemText. - No help file. Starting a new game causes the window to drop one pixel (Peter Hunnisett) diff --git a/programs/winemine/main.c b/programs/winemine/main.c index 5e3ab4a923b..a8ea08ec7eb 100644 --- a/programs/winemine/main.c +++ b/programs/winemine/main.c @@ -176,7 +176,7 @@ LRESULT WINAPI MainProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_MOUSEMOVE: { - if( (wParam & MK_LBUTTON) && (wParam & MK_RBUTTON) ) { + if( wParam & MK_MBUTTON ) { msg = WM_MBUTTONDOWN; } else if( wParam & MK_LBUTTON ) { @@ -277,7 +277,7 @@ void LoadBoard( BOARD *p_board ) DWORD size; DWORD type; HKEY hkey; - char data[16]; + char data[MAX_PLAYER_NAME_SIZE+1]; char key_name[8]; unsigned i; @@ -327,7 +327,7 @@ void LoadBoard( BOARD *p_board ) (LPDWORD) &size ) == ERROR_SUCCESS ) lstrcpynA( p_board->best_name[i], data, sizeof(p_board->best_name[i]) ); else - LoadString( p_board->hInst, IDS_NOBODY, p_board->best_name[i], 16 ); + LoadString( p_board->hInst, IDS_NOBODY, p_board->best_name[i], MAX_PLAYER_NAME_SIZE+1 ); } for( i = 0; i < 3; i++ ) { @@ -345,7 +345,7 @@ void SaveBoard( BOARD *p_board ) { HKEY hkey; unsigned i; - char data[16]; + char data[MAX_PLAYER_NAME_SIZE+1]; char key_name[8]; if( RegCreateKeyEx( HKEY_CURRENT_USER, registry_key, @@ -452,13 +452,24 @@ static void MoveOnScreen(RECT* rect) void CreateBoard( BOARD *p_board ) { int left, top, bottom, right; + unsigned col, row; RECT wnd_rect; p_board->mb = MB_NONE; p_board->boxes_left = p_board->cols * p_board->rows - p_board->mines; p_board->num_flags = 0; - CreateBoxes( p_board ); + /* Create the boxes... + * We actually create them with an empty border, + * so special care doesn't have to be taken on the edges + */ + for( col = 0; col <= p_board->cols + 1; col++ ) + for( row = 0; row <= p_board->rows + 1; row++ ) { + p_board->box[col][row].IsPressed = FALSE; + p_board->box[col][row].IsMine = FALSE; + p_board->box[col][row].FlagType = NORMAL; + p_board->box[col][row].NumMines = 0; + } p_board->width = p_board->cols * MINE_WIDTH + BOARD_WMARGIN * 2; @@ -531,30 +542,21 @@ void CheckLevel( BOARD *p_board ) if( p_board->mines < BEGINNER_MINES ) p_board->mines = BEGINNER_MINES; - if( p_board->mines > p_board->cols * p_board->rows - 1 ) - p_board->mines = p_board->cols * p_board->rows - 1; + if( p_board->mines > p_board->cols * p_board->rows - 2 ) + p_board->mines = p_board->cols * p_board->rows - 2; } - -void CreateBoxes( BOARD *p_board ) +/* Randomly places mines everywhere except the selected box. */ +void PlaceMines ( BOARD *p_board, int selected_col, int selected_row ) { int i, j; unsigned col, row; srand( (unsigned) time( NULL ) ); - /* Create the boxes... - * We actually create them with an empty border, - * so special care doesn't have to be taken on the edges - */ - - for( col = 0; col <= p_board->cols + 1; col++ ) - for( row = 0; row <= p_board->rows + 1; row++ ) { - p_board->box[col][row].IsPressed = FALSE; - p_board->box[col][row].IsMine = FALSE; - p_board->box[col][row].FlagType = NORMAL; - p_board->box[col][row].NumMines = 0; - } + /* Temporarily place a mine at the selected box until all the other + * mines are placed, this avoids checking in the mine creation loop. */ + p_board->box[selected_col][selected_row].IsMine = TRUE; /* create mines */ i = 0; @@ -568,11 +570,13 @@ void CreateBoxes( BOARD *p_board ) } } + /* Remove temporarily placed mine for selected box */ + p_board->box[selected_col][selected_row].IsMine = FALSE; + /* * Now we label the remaining boxes with the * number of mines surrounding them. */ - for( col = 1; col < p_board->cols + 1; col++ ) for( row = 1; row < p_board->rows + 1; row++ ) { for( i = -1; i <= 1; i++ ) @@ -700,11 +704,6 @@ void DrawLeds( HDC hdc, HDC hMemDC, BOARD *p_board, int number, int x, int y ) led[i] = 10; } - /* use unlit led if not playing */ - if( p_board->status == WAITING ) - for( i = 0; i < 3; i++ ) - led[i] = 11; - hOldObj = SelectObject (hMemDC, p_board->hLedsBMP); for( i = 0; i < 3; i++ ) { @@ -838,8 +837,12 @@ void TestMines( BOARD *p_board, POINT pt, int msg ) p_board->press.x, p_board->press.y ); p_board->press.x = 0; p_board->press.y = 0; - if( p_board->box[col][row].FlagType != FLAG ) + if( p_board->box[col][row].FlagType != FLAG + && p_board->status != PLAYING ) + { p_board->status = PLAYING; + PlaceMines( p_board, col, row ); + } CompleteBox( p_board, col, row ); break; @@ -859,7 +862,6 @@ void TestMines( BOARD *p_board, POINT pt, int msg ) case WM_RBUTTONDOWN: AddFlag( p_board, col, row ); - p_board->status = PLAYING; break; default: WINE_TRACE("Unknown message type received in TestMines\n"); diff --git a/programs/winemine/main.h b/programs/winemine/main.h index 1b818cb0804..a813c95f04a 100644 --- a/programs/winemine/main.h +++ b/programs/winemine/main.h @@ -19,8 +19,8 @@ #include #define BEGINNER_MINES 10 -#define BEGINNER_COLS 8 -#define BEGINNER_ROWS 8 +#define BEGINNER_COLS 9 +#define BEGINNER_ROWS 9 #define ADVANCED_MINES 40 #define ADVANCED_COLS 16 @@ -45,6 +45,8 @@ #define FACE_WIDTH 24 #define FACE_HEIGHT 24 +#define MAX_PLAYER_NAME_SIZE 31 + typedef enum { SPRESS_BMP, COOL_BMP, DEAD_BMP, OOH_BMP, SMILE_BMP } FACE_BMP; typedef enum { WAITING, PLAYING, GAMEOVER, WON } GAME_STATUS; @@ -84,7 +86,7 @@ typedef struct tagBOARD unsigned rows; unsigned cols; unsigned mines; - char best_name [3][16]; + char best_name [3][MAX_PLAYER_NAME_SIZE+1]; DWORD best_time [3]; DIFFICULTY difficulty; @@ -134,7 +136,7 @@ void CheckLevel( BOARD *p_board ); void CreateBoard( BOARD *p_board ); -void CreateBoxes( BOARD *p_board ); +void PlaceMines ( BOARD *p_board, int selected_col, int selected_row ); void TestBoard( HWND hWnd, BOARD *p_board, int x, int y, int msg ); diff --git a/programs/winetest/Makefile.in b/programs/winetest/Makefile.in index e7c6fb6a470..89e0f5d9a41 100644 --- a/programs/winetest/Makefile.in +++ b/programs/winetest/Makefile.in @@ -50,6 +50,7 @@ TESTBINS = \ hlink_test.exe \ imm32_test.exe \ inetcomm_test.exe \ + inetmib1_test.exe \ infosoft_test.exe \ iphlpapi_test.exe \ itss_test.exe \ @@ -157,6 +158,8 @@ imm32_test.exe: $(DLLDIR)/imm32/tests/imm32_test.exe$(DLLEXT) cp $(DLLDIR)/imm32/tests/imm32_test.exe$(DLLEXT) $@ && $(STRIP) $@ inetcomm_test.exe: $(DLLDIR)/inetcomm/tests/inetcomm_test.exe$(DLLEXT) cp $(DLLDIR)/inetcomm/tests/inetcomm_test.exe$(DLLEXT) $@ && $(STRIP) $@ +inetmib1_test.exe: $(DLLDIR)/inetmib1/tests/inetmib1_test.exe$(DLLEXT) + cp $(DLLDIR)/inetmib1/tests/inetmib1_test.exe$(DLLEXT) $@ && $(STRIP) $@ infosoft_test.exe: $(DLLDIR)/infosoft/tests/infosoft_test.exe$(DLLEXT) cp $(DLLDIR)/infosoft/tests/infosoft_test.exe$(DLLEXT) $@ && $(STRIP) $@ iphlpapi_test.exe: $(DLLDIR)/iphlpapi/tests/iphlpapi_test.exe$(DLLEXT) diff --git a/programs/winetest/winetest.rc b/programs/winetest/winetest.rc index 05b28c3107d..5c78c8f44d2 100644 --- a/programs/winetest/winetest.rc +++ b/programs/winetest/winetest.rc @@ -111,6 +111,7 @@ gdiplus_test.exe TESTRES "gdiplus_test.exe" hlink_test.exe TESTRES "hlink_test.exe" imm32_test.exe TESTRES "imm32_test.exe" inetcomm_test.exe TESTRES "inetcomm_test.exe" +inetmib1_test.exe TESTRES "inetmib1_test.exe" infosoft_test.exe TESTRES "infosoft_test.exe" iphlpapi_test.exe TESTRES "iphlpapi_test.exe" itss_test.exe TESTRES "itss_test.exe" diff --git a/programs/winhlp32/Bg.rc b/programs/winhlp32/Bg.rc index c2d47e1c7c3..920aec79b48 100644 --- a/programs/winhlp32/Bg.rc +++ b/programs/winhlp32/Bg.rc @@ -38,6 +38,22 @@ MAIN_MENU MENU LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT POPUP "&Îòìåòêè" { MENUITEM "&Çàäàé...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Ïîìîù" { MENUITEM "Ïîìîù &çà ïîìîùòà", MNID_HELP_HELPON MENUITEM "Âèíàãè îò&ãîðå", MNID_HELP_HELPTOP @@ -61,7 +77,6 @@ STID_HLPFILE_ERROR_s, " STID_CONTENTS, "&Ñúäúðæàíèå" STID_SEARCH, "&Òúðñè" STID_BACK, "&Íàçàä" -STID_HISTORY, "&Èñòîðèÿ" STID_TOPICS, "&Òåìè" STID_ALL_FILES, "Âñè÷êè ôàéëîâå (*.*)" STID_HELP_FILES_HLP, "Ïîìîùíè ôàéëîâå (*.hlp)" diff --git a/programs/winhlp32/Cs.rc b/programs/winhlp32/Cs.rc index a3ca70815ff..d457e3c52b7 100644 --- a/programs/winhlp32/Cs.rc +++ b/programs/winhlp32/Cs.rc @@ -43,6 +43,22 @@ MAIN_MENU MENU LANGUAGE LANG_CZECH, SUBLANG_DEFAULT POPUP "&Záložka" { MENUITEM "Pøi&dat...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Nápovìda" { MENUITEM "Náp&ovìda k nápovìdì", MNID_HELP_HELPON MENUITEM "Vždy na &vrchu", MNID_HELP_HELPTOP @@ -66,7 +82,6 @@ STID_HLPFILE_ERROR_s, "Nelze p STID_CONTENTS, "&Obsah" STID_SEARCH, "&Hledat" STID_BACK, "&Zpìt" -STID_HISTORY, "&Historie" STID_TOPICS, "&Témata" STID_ALL_FILES, "Všechny soubory (*.*)" STID_HELP_FILES_HLP, "Soubory nápovìdy (*.hlp)" diff --git a/programs/winhlp32/Da.rc b/programs/winhlp32/Da.rc index 77569cd84fe..3671d8bb761 100644 --- a/programs/winhlp32/Da.rc +++ b/programs/winhlp32/Da.rc @@ -40,6 +40,22 @@ MAIN_MENU MENU LANGUAGE LANG_DANISH, SUBLANG_DEFAULT POPUP "Bog&mærke" { MENUITEM "&Definer...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Hjælp" { MENUITEM "&Brug af Hjælp", MNID_HELP_HELPON MENUITEM "Altid &øverst", MNID_HELP_HELPTOP @@ -73,7 +89,6 @@ STID_HLPFILE_ERROR_s, "Fejl ved indl STID_CONTENTS, "&Indhold" STID_SEARCH, "&Søg" STID_BACK, "&Tilbage" -STID_HISTORY, "&Oversigt" STID_TOPICS, "&Emner" STID_ALL_FILES, "Alle filer (*.*)" STID_HELP_FILES_HLP, "Hjælpe filer (*.hlp)" diff --git a/programs/winhlp32/De.rc b/programs/winhlp32/De.rc index 846ef9baaf9..11ca356d482 100644 --- a/programs/winhlp32/De.rc +++ b/programs/winhlp32/De.rc @@ -39,6 +39,22 @@ MAIN_MENU MENU LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL POPUP "&Lesezeichen" { MENUITEM "&Definieren...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Hilfe" { MENUITEM "&Hilfe benutzen", MNID_HELP_HELPON MENUITEM "Immer im &Vordergrund", MNID_HELP_HELPTOP @@ -73,7 +89,6 @@ STID_HLPFILE_ERROR_s, "Fehler beim Lesen der Hilfe-Datei `%s'" STID_CONTENTS, "&Inhalt" STID_SEARCH, "&Suchen" STID_BACK, "&Zurück" -STID_HISTORY, "&Chronik" STID_TOPICS, "&Themen" STID_ALL_FILES, "Alle Dateien (*.*)" STID_HELP_FILES_HLP, "Hilfe-Dateien (*.hlp)" diff --git a/programs/winhlp32/En.rc b/programs/winhlp32/En.rc index 40d61a26c87..0eb9269acf5 100644 --- a/programs/winhlp32/En.rc +++ b/programs/winhlp32/En.rc @@ -39,6 +39,22 @@ MAIN_MENU MENU LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT POPUP "&Bookmark" { MENUITEM "&Define...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Help" { MENUITEM "Help &on help", MNID_HELP_HELPON MENUITEM "Always on &top", MNID_HELP_HELPTOP @@ -72,7 +88,6 @@ STID_HLPFILE_ERROR_s, "Error while reading the help file `%s'" STID_CONTENTS, "&Contents" STID_SEARCH, "&Search" STID_BACK, "&Back" -STID_HISTORY, "&History" STID_TOPICS, "&Topics" STID_ALL_FILES, "All files (*.*)" STID_HELP_FILES_HLP, "Help files (*.hlp)" diff --git a/programs/winhlp32/Eo.rc b/programs/winhlp32/Eo.rc index 7fd946cce33..a62634ebe65 100644 --- a/programs/winhlp32/Eo.rc +++ b/programs/winhlp32/Eo.rc @@ -41,6 +41,22 @@ MAIN_MENU MENU LANGUAGE LANG_ESPERANTO, SUBLANG_DEFAULT POPUP "&Legosigno" { MENUITEM "&Difinu...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Helpo" { MENUITEM "&Helpu pri helpo", MNID_HELP_HELPON MENUITEM "Æiam &supre", MNID_HELP_HELPTOP @@ -64,7 +80,6 @@ STID_HLPFILE_ERROR_s, "Eraro dum la legado de helpdosiero `%s'" STID_CONTENTS, "&Enhavo" STID_SEARCH, "&Seræu" STID_BACK, "&Retro" -STID_HISTORY, "Krono&logio" STID_TOPICS, "&Temoj" STID_ALL_FILES, "Tutaj dosieroj (*.*)" STID_HELP_FILES_HLP, "Helpaj dosieroj (*.hlp)" diff --git a/programs/winhlp32/Es.rc b/programs/winhlp32/Es.rc index 7825c248c2c..06120a4b713 100644 --- a/programs/winhlp32/Es.rc +++ b/programs/winhlp32/Es.rc @@ -40,6 +40,22 @@ MAIN_MENU MENU LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL POPUP "&Marcador" { MENUITEM "&Definir...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "A&yuda" { MENUITEM "&Ayuda sobre la ayuda", MNID_HELP_HELPON MENUITEM "&Siempre visible", MNID_HELP_HELPTOP @@ -63,7 +79,6 @@ STID_HLPFILE_ERROR_s, "Error al leer el archivo de ayuda `%s'" STID_CONTENTS, "&Índice" STID_SEARCH, "&Buscar" STID_BACK, "&Anterior" -STID_HISTORY, "&Historial" STID_TOPICS, "&Temas" STID_ALL_FILES, "Todos los archivos (*.*)" STID_HELP_FILES_HLP, "Archivos de ayuda (*.hlp)" diff --git a/programs/winhlp32/Fi.rc b/programs/winhlp32/Fi.rc index cd5164c910c..860e5db3ce4 100644 --- a/programs/winhlp32/Fi.rc +++ b/programs/winhlp32/Fi.rc @@ -40,6 +40,22 @@ MAIN_MENU MENU LANGUAGE LANG_FINNISH, SUBLANG_DEFAULT POPUP "&Kirjanmerkki" { MENUITEM "&Aseta...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Ohje" { MENUITEM "&Ohjeen käyttö", MNID_HELP_HELPON MENUITEM "&Aina päällimmäisenä", MNID_HELP_HELPTOP @@ -64,7 +80,6 @@ STID_HLPFILE_ERROR_s, "Virhe luettaessa ohjetiedostoa `%s'" STID_CONTENTS, "&Sisällys" STID_SEARCH, "&Etsi" STID_BACK, "&Takaisin" -STID_HISTORY, "&Luetut" STID_TOPICS, "T&opics" STID_ALL_FILES, "Kaikki tiedostot (*.*)" STID_HELP_FILES_HLP, "Ohjetiedostot (*.hlp)" diff --git a/programs/winhlp32/Fr.rc b/programs/winhlp32/Fr.rc index 32c3efbdd01..a706d882f8e 100644 --- a/programs/winhlp32/Fr.rc +++ b/programs/winhlp32/Fr.rc @@ -42,6 +42,22 @@ MAIN_MENU MENU POPUP "&Signet" { MENUITEM "&Définir...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Aide toujours visible" + BEGIN + MENUITEM "Par défaut", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "Historique", MNID_OPTS_HISTORY + POPUP "Polices" + BEGIN + MENUITEM "Petite", MNID_OPTS_FONTS_SMALL + MENUITEM "Normale", MNID_OPTS_FONTS_NORMAL + MENUITEM "Grande", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Utiliser les couleurs système", MNID_OPTS_SYSTEM_COLORS +} POPUP "Aid&e" { MENUITEM "&Utiliser l'aide", MNID_HELP_HELPON MENUITEM "&Toujours visible", MNID_HELP_HELPTOP @@ -75,7 +91,6 @@ STID_HLPFILE_ERROR_s, "Une erreur est survenue en lisant le fichier d'aide STID_CONTENTS, "&Index" STID_SEARCH, "&Rechercher" STID_BACK, "&Précédent" -STID_HISTORY, "&Historique" STID_TOPICS, "&Sujets" STID_ALL_FILES, "Tous fichiers (*.*)" STID_HELP_FILES_HLP, "Fichiers d'aide (*.hlp)" diff --git a/programs/winhlp32/Hu.rc b/programs/winhlp32/Hu.rc index e502e6e16b3..eddafe34029 100644 --- a/programs/winhlp32/Hu.rc +++ b/programs/winhlp32/Hu.rc @@ -40,6 +40,22 @@ MAIN_MENU MENU LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT POPUP "&Könyvjelzõ" { MENUITEM "&Definiálás...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Súgó" { MENUITEM "&Használat", MNID_HELP_HELPON MENUITEM "Mindig &legfelül", MNID_HELP_HELPTOP @@ -64,7 +80,6 @@ STID_HLPFILE_ERROR_s, "Hiba a `%s' file olvas STID_CONTENTS, "&Tartalom" STID_SEARCH, "&Keresés" STID_BACK, "&Vissza" -STID_HISTORY, "&Elõzmény" STID_TOPICS, "&Témakörök" STID_ALL_FILES, "Minden fájl (*.*)" STID_HELP_FILES_HLP, "Súgó fájlok (*.hlp)" diff --git a/programs/winhlp32/It.rc b/programs/winhlp32/It.rc index 6d814e845c6..a294fcc8a5c 100644 --- a/programs/winhlp32/It.rc +++ b/programs/winhlp32/It.rc @@ -39,6 +39,22 @@ MAIN_MENU MENU LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL POPUP "&Segnalibro" { MENUITEM "&Definisci...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&?" { MENUITEM "&Aiuto sulla guida", MNID_HELP_HELPON MENUITEM "Sempre in primo &piano", MNID_HELP_HELPTOP @@ -63,7 +79,6 @@ STID_HLPFILE_ERROR_s, "Errore di lettura del file della Guida `%s'" STID_CONTENTS, "&Sommario" STID_SEARCH, "&Trova" STID_BACK, "&Precedente" -STID_HISTORY, "&Cronologia" STID_TOPICS, "&Argomenti" STID_ALL_FILES, "Tutti i file (*.*)" STID_HELP_FILES_HLP, "File della Guida (*.hlp)" diff --git a/programs/winhlp32/Ko.rc b/programs/winhlp32/Ko.rc index b1152dc6940..32289db5e21 100644 --- a/programs/winhlp32/Ko.rc +++ b/programs/winhlp32/Ko.rc @@ -39,6 +39,22 @@ MAIN_MENU MENU LANGUAGE LANG_KOREAN, SUBLANG_NEUTRAL POPUP "Ã¥°¥ÇÇ(&B)" { MENUITEM "Á¤ÀÇ(&D)...", MNID_BKMK_DEFINE } + POPUP "¿É¼Ç(&O)" { + POPUP "°¡´ÉÇÑ µµ¿ò¸» º¸À̱â" + BEGIN + MENUITEM "±âº»", MNID_OPTS_HELP_DEFAULT + MENUITEM "º¸À̱â", MNID_OPTS_HELP_VISIBLE + MENUITEM "º¸¿©ÁÖÁö ¾Ê±â", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "±â·Ï", MNID_OPTS_HISTORY + POPUP "±Û²Ã" + BEGIN + MENUITEM "ÀÛ°Ô", MNID_OPTS_FONTS_SMALL + MENUITEM "º¸Åë", MNID_OPTS_FONTS_NORMAL + MENUITEM "Å©°Ô", MNID_OPTS_FONTS_LARGE + END + MENUITEM "½Ã½ºÅÛ »ö»ó »ç¿ë", MNID_OPTS_SYSTEM_COLORS + } POPUP "µµ¿ò¸»(&H)" { MENUITEM "µµ¿ò¸» »ç¿ë¹ý(&O)", MNID_HELP_HELPON MENUITEM "Ç×»ó À§(&T)", MNID_HELP_HELPTOP @@ -75,7 +91,6 @@ STID_HLPFILE_ERROR_s, " STID_CONTENTS, "¸ñÂ÷(&C)" STID_SEARCH, "ã±â(&S)" STID_BACK, "µÚ·Î(&B)" -STID_HISTORY, "È÷½ºÅ丮(&H)" STID_TOPICS, "¸ñÂ÷(&T)" STID_ALL_FILES, "¸ðµç ÆÄÀÏ (*.*)" STID_HELP_FILES_HLP, "µµ¿ò¸» ÆÄÀÏ (*.hlp)" diff --git a/programs/winhlp32/Nl.rc b/programs/winhlp32/Nl.rc index ead97e74ae6..b3fc34c80a6 100644 --- a/programs/winhlp32/Nl.rc +++ b/programs/winhlp32/Nl.rc @@ -39,6 +39,22 @@ MAIN_MENU MENU LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL POPUP "&Favorieten" { MENUITEM "&Aanmaken...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Help" { MENUITEM "Hulp &bij help", MNID_HELP_HELPON MENUITEM "Altijd &zichtbaar", MNID_HELP_HELPTOP @@ -72,7 +88,6 @@ STID_HLPFILE_ERROR_s, "Fout bij het lezen van het helpbestand `%s'" STID_CONTENTS, "&Inhoud" STID_SEARCH, "&Zoeken" STID_BACK, "&Terug" -STID_HISTORY, "&Geschiedenis" STID_TOPICS, "&Onderwerpen" STID_ALL_FILES, "Alle bestanden (*.*)" STID_HELP_FILES_HLP, "Helpbestanden (*.hlp)" diff --git a/programs/winhlp32/No.rc b/programs/winhlp32/No.rc index b9a05e7f755..2e76649e4bd 100644 --- a/programs/winhlp32/No.rc +++ b/programs/winhlp32/No.rc @@ -38,6 +38,22 @@ MAIN_MENU MENU LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL POPUP "&Bokmerke" { MENUITEM "&Definer...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Hjelp" { MENUITEM "&Hjelp til Hjelp", MNID_HELP_HELPON MENUITEM "All&tid øverst", MNID_HELP_HELPTOP @@ -71,7 +87,6 @@ STID_HLPFILE_ERROR_s, "Feil ved lesing av hjelpefilen '%s'" STID_CONTENTS, "&Innhold" STID_SEARCH, "&Søk" STID_BACK, "Til&bake" -STID_HISTORY, "&Historikk" STID_TOPICS, "&Emner" STID_ALL_FILES, "Alle filer (*.*)" STID_HELP_FILES_HLP, "Hjelp-filer (*.hlp)" diff --git a/programs/winhlp32/Pl.rc b/programs/winhlp32/Pl.rc index 6b3a7679add..bea1693dbcf 100644 --- a/programs/winhlp32/Pl.rc +++ b/programs/winhlp32/Pl.rc @@ -40,6 +40,22 @@ MAIN_MENU MENU LANGUAGE LANG_POLISH, SUBLANG_DEFAULT POPUP "&Zak³adka" { MENUITEM "&Zdefiniuj...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "Pomo&c" { MENUITEM "&Pomoc", MNID_HELP_HELPON MENUITEM "&Zawsze na wierzchu", MNID_HELP_HELPTOP @@ -73,7 +89,6 @@ STID_HLPFILE_ERROR_s, "B STID_CONTENTS, "&Zawartoœæ" STID_SEARCH, "&Szukaj" STID_BACK, "&Wstecz" -STID_HISTORY, "&Historia" STID_TOPICS, "&Tematy" STID_ALL_FILES, "Wszystkie pliki (*.*)" STID_HELP_FILES_HLP, "Pliki pomocy (*.hlp)" diff --git a/programs/winhlp32/Pt.rc b/programs/winhlp32/Pt.rc index 114d5020967..6c6cdbbb849 100644 --- a/programs/winhlp32/Pt.rc +++ b/programs/winhlp32/Pt.rc @@ -45,6 +45,22 @@ MAIN_MENU MENU POPUP "In&dicador" { MENUITEM "&Definir...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "Aj&uda" { MENUITEM "Ajuda &na ajuda", MNID_HELP_HELPON MENUITEM "Sempre &visível", MNID_HELP_HELPTOP @@ -76,6 +92,22 @@ MAIN_MENU MENU POPUP "In&dicador" { MENUITEM "&Definir...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "Aj&uda" { MENUITEM "Ajuda &na ajuda", MNID_HELP_HELPON MENUITEM "Sempre &visível", MNID_HELP_HELPTOP @@ -102,7 +134,6 @@ STID_HLPFILE_ERROR_s, "Erro encontrado na leitura do arquivo de ajuda '%s'" STID_CONTENTS, "&Conteúdo" STID_SEARCH, "&Procurar" STID_BACK, "&Voltar" -STID_HISTORY, "&Histórico" STID_TOPICS, "&Tópicos" STID_ALL_FILES, "Todos os arquivos (*.*)" STID_HELP_FILES_HLP, "Arquivos de ajuda (*.hlp)" @@ -123,7 +154,6 @@ STID_HLPFILE_ERROR_s, "Erro encontrado na leitura do ficheiro de ajuda '%s'" STID_CONTENTS, "&Conteúdo" STID_SEARCH, "&Procurar" STID_BACK, "&Voltar" -STID_HISTORY, "&Histórico" STID_TOPICS, "&Tópicos" STID_ALL_FILES, "Todos os ficheiros (*.*)" STID_HELP_FILES_HLP, "Ficheiros de ajuda (*.hlp)" diff --git a/programs/winhlp32/Rm.rc b/programs/winhlp32/Rm.rc index 16940942969..cbcd16c5d00 100644 --- a/programs/winhlp32/Rm.rc +++ b/programs/winhlp32/Rm.rc @@ -43,6 +43,22 @@ MAIN_MENU MENU LANGUAGE LANG_ROMANSH, SUBLANG_DEFAULT POPUP "&Marca" { MENUITEM "&Definir...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Ag�d" { MENUITEM "&Douvrar l'ag�d", MNID_HELP_HELPON MENUITEM "Ad�na da&vant", MNID_HELP_HELPTOP @@ -66,7 +82,6 @@ STID_HLPFILE_ERROR_s, "Sbagl cun leger la datoteca d'ag�d `%s'" STID_CONTENTS, "&Cuntgn�" STID_SEARCH, "&Tscherchar" STID_BACK, "&Inavo" -STID_HISTORY, "&Fin qua" STID_TOPICS, "T&opics" STID_ALL_FILES, "Tuot las datotecas (*.*)" STID_HELP_FILES_HLP, "Datotecas d'ag�d (*.hlp)" diff --git a/programs/winhlp32/Ru.rc b/programs/winhlp32/Ru.rc index 4f760a7f3fd..0d327282eb3 100644 --- a/programs/winhlp32/Ru.rc +++ b/programs/winhlp32/Ru.rc @@ -38,6 +38,22 @@ MAIN_MENU MENU LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT POPUP "&Çàêëàäêà" { MENUITEM "&Îïðåäåëèòü...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Ñïðàâêà" { MENUITEM "Ïîìîùü &ïî ïîìîùè", MNID_HELP_HELPON MENUITEM "Âñåãäà &ñâåðõó", MNID_HELP_HELPTOP @@ -71,7 +87,6 @@ STID_HLPFILE_ERROR_s, " STID_CONTENTS, "&Ñîäåðæàíèå" STID_SEARCH, "&Íàéòè" STID_BACK, "&Íàçàä" -STID_HISTORY, "&Èñòîðèÿ" STID_TOPICS, "&Óêàçàòåëü" STID_ALL_FILES, "Âñå ôàéëû (*.*)" STID_HELP_FILES_HLP, "Ôàéëû ñïðàâêè (*.hlp)" diff --git a/programs/winhlp32/Si.rc b/programs/winhlp32/Si.rc index 1975d97c07e..da9448b739a 100644 --- a/programs/winhlp32/Si.rc +++ b/programs/winhlp32/Si.rc @@ -40,7 +40,23 @@ MAIN_MENU MENU LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT POPUP "&Zaznamki" { MENUITEM "Do&loči ...", MNID_BKMK_DEFINE } - POPUP "&Pomoč" { + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } + POPUP "&Pomoč" { MENUITEM "&O pomoči", MNID_HELP_HELPON MENUITEM "Vedno na &vrhu", MNID_HELP_HELPTOP MENUITEM SEPARATOR @@ -73,7 +89,6 @@ STID_HLPFILE_ERROR_s, "Napaka pri branju datoteke s pomočjo `%s'" STID_CONTENTS, "&Teme pomoči" STID_SEARCH, "&Iskanje" STID_BACK, "&Nazaj" -STID_HISTORY, "&Zgodovina" STID_TOPICS, "&Vsebina" STID_ALL_FILES, "Vse datoteke (*.*)" STID_HELP_FILES_HLP, "Datoteke s pomočjo (*.hlp)" diff --git a/programs/winhlp32/Sk.rc b/programs/winhlp32/Sk.rc index 14398363ada..eeb766e02d6 100644 --- a/programs/winhlp32/Sk.rc +++ b/programs/winhlp32/Sk.rc @@ -36,6 +36,22 @@ MAIN_MENU MENU LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT POPUP "&Záložka" { MENUITEM "&Definova�...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Pomoc" { MENUITEM "Pomoc &na pomoci", MNID_HELP_HELPON MENUITEM "Vždy na &vrchu", MNID_HELP_HELPTOP @@ -59,7 +75,6 @@ STID_HLPFILE_ERROR_s, "Chyba po STID_CONTENTS, "&Obsah" STID_SEARCH, "&H¾ada�" STID_BACK, "&Spä�" -STID_HISTORY, "&História" STID_TOPICS, "&Topics" STID_ALL_FILES, "Všetky súbory (*.*)" STID_HELP_FILES_HLP, "Súbory pomoci (*.hlp)" diff --git a/programs/winhlp32/Sv.rc b/programs/winhlp32/Sv.rc index 1c4c6851663..2991ad07ee1 100644 --- a/programs/winhlp32/Sv.rc +++ b/programs/winhlp32/Sv.rc @@ -41,6 +41,22 @@ MAIN_MENU MENU LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL POPUP "&Bokmärke" { MENUITEM "&Definiera...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Hjälp" { MENUITEM "Hjälp &för hjälp", MNID_HELP_HELPON MENUITEM "Alltid &överst", MNID_HELP_HELPTOP @@ -64,7 +80,6 @@ STID_HLPFILE_ERROR_s, "Fel vid läsning av hjälpfilen `%s'" STID_CONTENTS, "&Innehåll" STID_SEARCH, "&Sök" STID_BACK, "&Bakåt" -STID_HISTORY, "&Historik" STID_TOPICS, "&Ämnen" STID_ALL_FILES, "Alla filer (*.*)" STID_HELP_FILES_HLP, "Hjälpfiler (*.hlp)" diff --git a/programs/winhlp32/Tr.rc b/programs/winhlp32/Tr.rc index 9aa45f8c72b..ce5501f2c50 100644 --- a/programs/winhlp32/Tr.rc +++ b/programs/winhlp32/Tr.rc @@ -38,6 +38,22 @@ MAIN_MENU MENU LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT POPUP "Yer Ý&mleri" { MENUITEM "&Tanýmla...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Yardým" { MENUITEM "&Yardým Kullanýmý", MNID_HELP_HELPON MENUITEM "&Her Zaman Üstte", MNID_HELP_HELPTOP @@ -61,7 +77,6 @@ STID_HLPFILE_ERROR_s, "'%s' yard STID_CONTENTS, "&Ýçindekiler" STID_SEARCH, "&Ara" STID_BACK, "&Geri" -STID_HISTORY, "Ge&çmiþ" STID_TOPICS, "&Konular" STID_ALL_FILES, "Tüm dosyalar (*.*)" STID_HELP_FILES_HLP, "Yardým dosyalarý (*.hlp)" diff --git a/programs/winhlp32/Wa.rc b/programs/winhlp32/Wa.rc index 23e47cc9932..1a47bc7b874 100644 --- a/programs/winhlp32/Wa.rc +++ b/programs/winhlp32/Wa.rc @@ -42,6 +42,22 @@ MAIN_MENU MENU LANGUAGE LANG_WALON, SUBLANG_DEFAULT POPUP "&Rimårkes" { MENUITEM "&Defini...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "&Aide" { MENUITEM "&Aide so l' Aide", MNID_HELP_HELPON MENUITEM "Todi &Visibe", MNID_HELP_HELPTOP @@ -66,7 +82,6 @@ STID_HLPFILE_ERROR_s, "Y STID_CONTENTS, "Å&dvins" STID_SEARCH, "C&werî" STID_BACK, "Èn &Erî" -STID_HISTORY, "&Istwere" STID_TOPICS, "&Topics" STID_ALL_FILES, "Tos les fitchîs (*.*)" STID_HELP_FILES_HLP, "Fitchîs d' aide (*.hlp)" diff --git a/programs/winhlp32/Zh.rc b/programs/winhlp32/Zh.rc index dad37df8931..ed9c8b468b6 100644 --- a/programs/winhlp32/Zh.rc +++ b/programs/winhlp32/Zh.rc @@ -39,6 +39,22 @@ MAIN_MENU MENU LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED POPUP "ÊéÇ©£¨&B£©" { MENUITEM "¶¨Ò壨&D£©...", MNID_BKMK_DEFINE } + POPUP "&Options" { + POPUP "Help always visible" + BEGIN + MENUITEM "Default", MNID_OPTS_HELP_DEFAULT + MENUITEM "Visible", MNID_OPTS_HELP_VISIBLE + MENUITEM "Non visible", MNID_OPTS_HELP_NONVISIBLE + END + MENUITEM "History", MNID_OPTS_HISTORY + POPUP "Fonts" + BEGIN + MENUITEM "Small", MNID_OPTS_FONTS_SMALL + MENUITEM "Normal", MNID_OPTS_FONTS_NORMAL + MENUITEM "Large", MNID_OPTS_FONTS_LARGE + END + MENUITEM "Use system colors", MNID_OPTS_SYSTEM_COLORS + } POPUP "°ïÖú£¨&H£©" { MENUITEM "ÈçºÎʹÓðïÖú£¨&O£©", MNID_HELP_HELPON MENUITEM "×ÜÊÇÔÚ×îÇ°Ã棨&T£©", MNID_HELP_HELPTOP @@ -62,7 +78,6 @@ STID_HLPFILE_ERROR_s, " STID_CONTENTS, "ÄÚÈÝ£¨&C£©" STID_SEARCH, "ËÑË÷£¨&S£©" STID_BACK, "·µ»Ø£¨&B£©" -STID_HISTORY, "ÀúÊ·£¨&H£©" STID_TOPICS, "Ö÷Ì⣨&T£©" STID_ALL_FILES, "ËùÓÐÎļþ (*.*)" STID_HELP_FILES_HLP, "°ïÖúÎļþ (*.hlp)" diff --git a/programs/winhlp32/winhelp.c b/programs/winhlp32/winhelp.c index 3b8f173a563..962a3a0c0e7 100644 --- a/programs/winhlp32/winhelp.c +++ b/programs/winhlp32/winhelp.c @@ -376,6 +376,13 @@ typedef struct WORD ofsData; } WINHELP,*LPWINHELP; +static BOOL WINHELP_HasWorkingWindow(void) +{ + if (!Globals.active_win) return FALSE; + if (Globals.active_win->next || Globals.win_list != Globals.active_win) return TRUE; + return Globals.active_win->page != NULL && Globals.active_win->page->file != NULL; +} + /****************************************************************** * WINHELP_HandleCommand * @@ -407,6 +414,7 @@ static LRESULT WINHELP_HandleCommand(HWND hSrcWnd, LPARAM lParam) { MACRO_JumpContext(ptr, "main", wh->data); } + if (!WINHELP_HasWorkingWindow()) MACRO_Exit(); break; case HELP_QUIT: MACRO_Exit(); @@ -416,9 +424,11 @@ static LRESULT WINHELP_HandleCommand(HWND hSrcWnd, LPARAM lParam) { MACRO_JumpContents(ptr, "main"); } + if (!WINHELP_HasWorkingWindow()) MACRO_Exit(); break; case HELP_HELPONHELP: MACRO_HelpOn(); + if (!WINHELP_HasWorkingWindow()) MACRO_Exit(); break; /* case HELP_SETINDEX: */ case HELP_SETCONTENTS: @@ -618,8 +628,6 @@ BOOL WINHELP_CreateHelpWindow(WINHELP_WNDPAGE* wpage, int nCmdShow, BOOL remembe LoadString(Globals.hInstance, STID_BACK, buffer, sizeof(buffer)); MACRO_CreateButton("BTN_BACK", buffer, "Back()"); if (win->back.index <= 1) MACRO_DisableButton("BTN_BACK"); - LoadString(Globals.hInstance, STID_HISTORY, buffer, sizeof(buffer)); - MACRO_CreateButton("BTN_HISTORY", buffer, "History()"); LoadString(Globals.hInstance, STID_TOPICS, buffer, sizeof(buffer)); MACRO_CreateButton("BTN_TOPICS", buffer, "Finder()"); } @@ -868,6 +876,8 @@ static LRESULT CALLBACK WINHELP_MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, case MNID_CTXT_ANNOTATE:MACRO_Annotate(); break; case MNID_CTXT_COPY: MACRO_CopyDialog(); break; case MNID_CTXT_PRINT: MACRO_Print(); break; + case MNID_OPTS_HISTORY: MACRO_History(); break; + case MNID_OPTS_FONTS_SMALL: case MNID_CTXT_FONTS_SMALL: win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0); if (win->font_scale != 0) @@ -876,6 +886,7 @@ static LRESULT CALLBACK WINHELP_MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, WINHELP_SetupText(GetDlgItem(hWnd, CTL_ID_TEXT), win, 0 /* FIXME */); } break; + case MNID_OPTS_FONTS_NORMAL: case MNID_CTXT_FONTS_NORMAL: win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0); if (win->font_scale != 1) @@ -884,6 +895,7 @@ static LRESULT CALLBACK WINHELP_MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, WINHELP_SetupText(GetDlgItem(hWnd, CTL_ID_TEXT), win, 0 /* FIXME */); } break; + case MNID_OPTS_FONTS_LARGE: case MNID_CTXT_FONTS_LARGE: win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0); if (win->font_scale != 2) @@ -892,6 +904,10 @@ static LRESULT CALLBACK WINHELP_MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, WINHELP_SetupText(GetDlgItem(hWnd, CTL_ID_TEXT), win, 0 /* FIXME */); } break; + case MNID_OPTS_HELP_DEFAULT: + case MNID_OPTS_HELP_VISIBLE: + case MNID_OPTS_HELP_NONVISIBLE: + case MNID_OPTS_SYSTEM_COLORS: case MNID_CTXT_HELP_DEFAULT: case MNID_CTXT_HELP_VISIBLE: case MNID_CTXT_HELP_NONVISIBLE: @@ -1028,6 +1044,16 @@ static LRESULT CALLBACK WINHELP_MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, } break; + case WM_INITMENUPOPUP: + win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0); + CheckMenuItem((HMENU)wParam, MNID_OPTS_FONTS_SMALL, + MF_BYCOMMAND | (win->font_scale == 0) ? MF_CHECKED : 0); + CheckMenuItem((HMENU)wParam, MNID_OPTS_FONTS_NORMAL, + MF_BYCOMMAND | (win->font_scale == 1) ? MF_CHECKED : 0); + CheckMenuItem((HMENU)wParam, MNID_OPTS_FONTS_LARGE, + MF_BYCOMMAND | (win->font_scale == 2) ? MF_CHECKED : 0); + break; + case WM_NCDESTROY: { BOOL bExit; diff --git a/programs/winhlp32/winhelp_res.h b/programs/winhlp32/winhelp_res.h index 3450859664e..3aa25a860de 100644 --- a/programs/winhlp32/winhelp_res.h +++ b/programs/winhlp32/winhelp_res.h @@ -8,10 +8,19 @@ #define MNID_BKMK_DEFINE 0x121 -#define MNID_HELP_HELPON 0x131 -#define MNID_HELP_HELPTOP 0x132 -#define MNID_HELP_ABOUT 0x141 -#define MNID_HELP_WINE 0x142 +#define MNID_OPTS_HELP_DEFAULT 0x131 +#define MNID_OPTS_HELP_VISIBLE 0x132 +#define MNID_OPTS_HELP_NONVISIBLE 0x133 +#define MNID_OPTS_HISTORY 0x134 +#define MNID_OPTS_FONTS_SMALL 0x135 +#define MNID_OPTS_FONTS_NORMAL 0x136 +#define MNID_OPTS_FONTS_LARGE 0x137 +#define MNID_OPTS_SYSTEM_COLORS 0x138 + +#define MNID_HELP_HELPON 0x141 +#define MNID_HELP_HELPTOP 0x142 +#define MNID_HELP_ABOUT 0x143 +#define MNID_HELP_WINE 0x144 #define MNID_CTXT_ANNOTATE 0x200 #define MNID_CTXT_COPY 0x201 @@ -36,7 +45,6 @@ #define STID_CONTENTS 0x126 #define STID_SEARCH 0x127 #define STID_BACK 0x128 -#define STID_HISTORY 0x129 #define STID_TOPICS 0x12A #define STID_ALL_FILES 0x12B #define STID_HELP_FILES_HLP 0x12C diff --git a/programs/wordpad/wordpad.c b/programs/wordpad/wordpad.c index f26e153cb0c..0900ea3f914 100644 --- a/programs/wordpad/wordpad.c +++ b/programs/wordpad/wordpad.c @@ -595,9 +595,9 @@ static void update_window(void) { RECT rect; - GetWindowRect(hMainWnd, &rect); + GetClientRect(hMainWnd, &rect); - (void) OnSize(hMainWnd, SIZE_RESTORED, MAKELONG(rect.bottom, rect.right)); + OnSize(hMainWnd, SIZE_RESTORED, MAKELPARAM(rect.right, rect.bottom)); } static BOOL is_bar_visible(int bandId) diff --git a/server/atom.c b/server/atom.c index f941c5124a7..eb0b782a569 100644 --- a/server/atom.c +++ b/server/atom.c @@ -43,7 +43,7 @@ #define MIN_HASH_SIZE 4 #define MAX_HASH_SIZE 0x200 -#define MAX_ATOM_LEN 255 +#define MAX_ATOM_LEN (255 * sizeof(WCHAR)) #define MIN_STR_ATOM 0xc000 #define MAX_ATOMS 0x4000 @@ -160,11 +160,11 @@ static atom_t add_atom_entry( struct atom_table *table, struct atom_entry *entry } /* compute the hash code for a string */ -static unsigned short atom_hash( struct atom_table *table, const WCHAR *str, data_size_t len ) +static unsigned short atom_hash( struct atom_table *table, const struct unicode_str *str ) { unsigned int i; unsigned short hash = 0; - for (i = 0; i < len; i++) hash ^= toupperW(str[i]) + i; + for (i = 0; i < str->len / sizeof(WCHAR); i++) hash ^= toupperW(str->str[i]) + i; return hash % table->entries_count; } @@ -184,7 +184,7 @@ static void atom_table_dump( struct object *obj, int verbose ) if (!entry) continue; fprintf( stderr, " %04x: ref=%d pinned=%c hash=%d \"", entry->atom, entry->count, entry->pinned ? 'Y' : 'N', entry->hash ); - dump_strW( entry->str, entry->len, stderr, "\"\""); + dump_strW( entry->str, entry->len / sizeof(WCHAR), stderr, "\"\""); fprintf( stderr, "\"\n" ); } } @@ -204,42 +204,42 @@ static void atom_table_destroy( struct object *obj ) } /* find an atom entry in its hash list */ -static struct atom_entry *find_atom_entry( struct atom_table *table, const WCHAR *str, - data_size_t len, unsigned short hash ) +static struct atom_entry *find_atom_entry( struct atom_table *table, const struct unicode_str *str, + unsigned short hash ) { struct atom_entry *entry = table->entries[hash]; while (entry) { - if (entry->len == len && !memicmpW( entry->str, str, len )) break; + if (entry->len == str->len && !memicmpW( entry->str, str->str, str->len/sizeof(WCHAR) )) break; entry = entry->next; } return entry; } /* add an atom to the table */ -static atom_t add_atom( struct atom_table *table, const WCHAR *str, data_size_t len ) +static atom_t add_atom( struct atom_table *table, const struct unicode_str *str ) { struct atom_entry *entry; - unsigned short hash = atom_hash( table, str, len ); + unsigned short hash = atom_hash( table, str ); atom_t atom = 0; - if (!len) + if (!str->len) { set_error( STATUS_OBJECT_NAME_INVALID ); return 0; } - if (len > MAX_ATOM_LEN) + if (str->len > MAX_ATOM_LEN) { set_error( STATUS_INVALID_PARAMETER ); return 0; } - if ((entry = find_atom_entry( table, str, len, hash ))) /* exists already */ + if ((entry = find_atom_entry( table, str, hash ))) /* exists already */ { entry->count++; return entry->atom; } - if ((entry = mem_alloc( sizeof(*entry) + (len - 1) * sizeof(WCHAR) ))) + if ((entry = mem_alloc( FIELD_OFFSET( struct atom_entry, str[str->len / sizeof(WCHAR)] ) ))) { if ((atom = add_atom_entry( table, entry ))) { @@ -249,8 +249,8 @@ static atom_t add_atom( struct atom_table *table, const WCHAR *str, data_size_t entry->count = 1; entry->pinned = 0; entry->hash = hash; - entry->len = len; - memcpy( entry->str, str, len * sizeof(WCHAR) ); + entry->len = str->len; + memcpy( entry->str, str->str, str->len ); } else free( entry ); } @@ -275,21 +275,21 @@ static void delete_atom( struct atom_table *table, atom_t atom, int if_pinned ) } /* find an atom in the table */ -static atom_t find_atom( struct atom_table *table, const WCHAR *str, data_size_t len ) +static atom_t find_atom( struct atom_table *table, const struct unicode_str *str ) { struct atom_entry *entry; - if (!len) + if (!str->len) { set_error( STATUS_OBJECT_NAME_INVALID ); return 0; } - if (len > MAX_ATOM_LEN) + if (str->len > MAX_ATOM_LEN) { set_error( STATUS_INVALID_PARAMETER ); return 0; } - if (table && (entry = find_atom_entry( table, str, len, atom_hash(table, str, len) ))) + if (table && (entry = find_atom_entry( table, str, atom_hash(table, str) ))) return entry->atom; set_error( STATUS_OBJECT_NAME_NOT_FOUND ); return 0; @@ -332,21 +332,21 @@ static struct atom_table *get_table( obj_handle_t h, int create ) } /* add an atom in the global table; used for window properties */ -atom_t add_global_atom( struct winstation *winstation, const WCHAR *str, data_size_t len ) +atom_t add_global_atom( struct winstation *winstation, const struct unicode_str *str ) { struct atom_table *global_table = get_global_table( winstation, 1 ); if (!global_table) return 0; - return add_atom( global_table, str, len ); + return add_atom( global_table, str ); } /* find an atom in the global table; used for window properties */ -atom_t find_global_atom( struct winstation *winstation, const WCHAR *str, data_size_t len ) +atom_t find_global_atom( struct winstation *winstation, const struct unicode_str *str ) { struct atom_table *global_table = get_global_table( winstation, 0 ); struct atom_entry *entry; - if (!len || len > MAX_ATOM_LEN || !global_table) return 0; - if ((entry = find_atom_entry( global_table, str, len, atom_hash(global_table, str, len) ))) + if (!str->len || str->len > MAX_ATOM_LEN || !global_table) return 0; + if ((entry = find_atom_entry( global_table, str, atom_hash(global_table, str) ))) return entry->atom; return 0; } @@ -381,10 +381,13 @@ void release_global_atom( struct winstation *winstation, atom_t atom ) /* add a global atom */ DECL_HANDLER(add_atom) { + struct unicode_str name; struct atom_table *table = get_table( req->table, 1 ); + if (table) { - reply->atom = add_atom( table, get_req_data(), get_req_data_size() / sizeof(WCHAR) ); + get_req_unicode_str( &name ); + reply->atom = add_atom( table, &name ); release_object( table ); } } @@ -403,10 +406,13 @@ DECL_HANDLER(delete_atom) /* find a global atom */ DECL_HANDLER(find_atom) { + struct unicode_str name; struct atom_table *table = get_table( req->table, 0 ); + if (table) { - reply->atom = find_atom( table, get_req_data(), get_req_data_size() / sizeof(WCHAR) ); + get_req_unicode_str( &name ); + reply->atom = find_atom( table, &name ); release_object( table ); } } @@ -421,12 +427,10 @@ DECL_HANDLER(get_atom_information) if ((entry = get_atom_entry( table, req->atom ))) { - data_size_t len = entry->len * sizeof(WCHAR); - if (get_reply_max_size()) - set_reply_data( entry->str, min( len, get_reply_max_size())); + set_reply_data( entry->str, min( entry->len, get_reply_max_size() )); reply->count = entry->count; reply->pinned = entry->pinned; - reply->total = len; + reply->total = entry->len; } else reply->count = -1; release_object( table ); diff --git a/server/class.c b/server/class.c index 334542ed7e2..5c30738dc82 100644 --- a/server/class.c +++ b/server/class.c @@ -128,6 +128,14 @@ int is_desktop_class( struct window_class *class ) return (class->atom == DESKTOP_ATOM && !class->local); } +int is_hwnd_message_class( struct window_class *class ) +{ + static const WCHAR messageW[] = {'M','e','s','s','a','g','e'}; + static const struct unicode_str name = { messageW, sizeof(messageW) }; + + return (!class->local && class->atom == find_global_atom( NULL, &name )); +} + atom_t get_class_atom( struct window_class *class ) { return class->atom; @@ -142,11 +150,13 @@ void *get_class_client_ptr( struct window_class *class ) DECL_HANDLER(create_class) { struct window_class *class; + struct unicode_str name; atom_t atom; - if (get_req_data_size()) + get_req_unicode_str( &name ); + if (name.len) { - atom = add_global_atom( NULL, get_req_data(), get_req_data_size() / sizeof(WCHAR) ); + atom = add_global_atom( NULL, &name ); if (!atom) return; } else @@ -187,10 +197,11 @@ DECL_HANDLER(create_class) DECL_HANDLER(destroy_class) { struct window_class *class; + struct unicode_str name; atom_t atom = req->atom; - if (get_req_data_size()) - atom = find_global_atom( NULL, get_req_data(), get_req_data_size() / sizeof(WCHAR) ); + get_req_unicode_str( &name ); + if (name.len) atom = find_global_atom( NULL, &name ); if (!(class = find_class( current->process, atom, req->instance ))) set_win32_error( ERROR_CLASS_DOES_NOT_EXIST ); diff --git a/server/object.h b/server/object.h index 0f311388138..cd46f5b8179 100644 --- a/server/object.h +++ b/server/object.h @@ -197,8 +197,8 @@ extern void init_signals(void); /* atom functions */ -extern atom_t add_global_atom( struct winstation *winstation, const WCHAR *str, data_size_t len ); -extern atom_t find_global_atom( struct winstation *winstation, const WCHAR *str, data_size_t len ); +extern atom_t add_global_atom( struct winstation *winstation, const struct unicode_str *str ); +extern atom_t find_global_atom( struct winstation *winstation, const struct unicode_str *str ); extern int grab_global_atom( struct winstation *winstation, atom_t atom ); extern void release_global_atom( struct winstation *winstation, atom_t atom ); diff --git a/server/process.c b/server/process.c index 023ffe9e642..9cbfe343a5a 100644 --- a/server/process.c +++ b/server/process.c @@ -459,18 +459,7 @@ static void process_poll_event( struct fd *fd, int event ) struct process *process = get_fd_user( fd ); assert( process->obj.ops == &process_ops ); - if (event & (POLLERR | POLLHUP)) - { - release_object( process->msg_fd ); - process->msg_fd = NULL; - if (process->sigkill_timeout) /* already waiting for it to die */ - { - remove_timeout_user( process->sigkill_timeout ); - process->sigkill_timeout = NULL; - process_died( process ); - } - else kill_process( process, 0 ); - } + if (event & (POLLERR | POLLHUP)) kill_process( process, 0 ); else if (event & POLLIN) receive_fd( process ); } @@ -737,6 +726,20 @@ void resume_process( struct process *process ) /* kill a process on the spot */ void kill_process( struct process *process, int violent_death ) { + if (!violent_death && process->msg_fd) /* normal termination on pipe close */ + { + release_object( process->msg_fd ); + process->msg_fd = NULL; + } + + if (process->sigkill_timeout) /* already waiting for it to die */ + { + remove_timeout_user( process->sigkill_timeout ); + process->sigkill_timeout = NULL; + process_died( process ); + return; + } + if (violent_death) terminate_process( process, NULL, 1 ); else { diff --git a/server/protocol.def b/server/protocol.def index dc5ac65ba33..1f60053fe29 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2118,7 +2118,8 @@ enum message_type @REQ(get_desktop_window) int force; /* force creation if it doesn't exist */ @REPLY - user_handle_t handle; /* handle to the desktop window */ + user_handle_t top_window; /* handle to the desktop window */ + user_handle_t msg_window; /* handle to the top-level HWND_MESSAGE parent */ @END diff --git a/server/trace.c b/server/trace.c index 2ae56ac4ca2..3c33c308848 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2638,7 +2638,8 @@ static void dump_get_desktop_window_request( const struct get_desktop_window_req static void dump_get_desktop_window_reply( const struct get_desktop_window_reply *req ) { - fprintf( stderr, " handle=%p", req->handle ); + fprintf( stderr, " top_window=%p,", req->top_window ); + fprintf( stderr, " msg_window=%p", req->msg_window ); } static void dump_set_window_owner_request( const struct set_window_owner_request *req ) diff --git a/server/user.h b/server/user.h index 908fa268124..666d561ea7f 100644 --- a/server/user.h +++ b/server/user.h @@ -58,6 +58,7 @@ struct desktop struct winstation *winstation; /* winstation this desktop belongs to */ struct list entry; /* entry in winstation list of desktops */ struct window *top_window; /* desktop window for this desktop */ + struct window *msg_window; /* HWND_MESSAGE top window */ struct hook_table *global_hooks; /* table of global hooks on this desktop */ struct timeout_user *close_timeout; /* timeout before closing the desktop */ unsigned int users; /* processes and threads using this desktop */ @@ -150,6 +151,7 @@ extern struct window_class *grab_class( struct process *process, atom_t atom, void *instance, int *extra_bytes ); extern void release_class( struct window_class *class ); extern int is_desktop_class( struct window_class *class ); +extern int is_hwnd_message_class( struct window_class *class ); extern atom_t get_class_atom( struct window_class *class ); extern void *get_class_client_ptr( struct window_class *class ); diff --git a/server/window.c b/server/window.c index a000cfc4bf9..1879b7c472c 100644 --- a/server/window.c +++ b/server/window.c @@ -393,8 +393,10 @@ void destroy_window( struct window *win ) list_remove( &win->entry ); if (is_desktop_window(win)) { - assert( win->desktop->top_window == win ); - win->desktop->top_window = NULL; + struct desktop *desktop = win->desktop; + assert( desktop->top_window == win || desktop->msg_window == win ); + if (desktop->top_window == win) desktop->top_window = NULL; + else desktop->msg_window = NULL; } detach_window_thread( win ); if (win->win_region) free_region( win->win_region ); @@ -426,7 +428,7 @@ static struct window *create_window( struct window *parent, struct window *owner { static const rectangle_t empty_rect; int extra_bytes; - struct window *win; + struct window *win = NULL; struct desktop *desktop; struct window_class *class; @@ -438,6 +440,27 @@ static struct window *create_window( struct window *parent, struct window *owner return NULL; } + if (!parent) /* null parent is only allowed for desktop or HWND_MESSAGE top window */ + { + if (is_desktop_class( class )) + parent = desktop->top_window; /* use existing desktop if any */ + else if (is_hwnd_message_class( class )) + /* use desktop window if message window is already created */ + parent = desktop->msg_window ? desktop->top_window : NULL; + else if (!(parent = desktop->top_window)) /* must already have a desktop then */ + { + set_error( STATUS_ACCESS_DENIED ); + goto failed; + } + } + + /* parent must be on the same desktop */ + if (parent && parent->desktop != desktop) + { + set_error( STATUS_ACCESS_DENIED ); + goto failed; + } + if (!(win = mem_alloc( sizeof(*win) + extra_bytes - 1 ))) goto failed; if (!(win->handle = alloc_user_handle( win, USER_WINDOW ))) goto failed; @@ -468,20 +491,6 @@ static struct window *create_window( struct window *parent, struct window *owner list_init( &win->children ); list_init( &win->unlinked ); - /* parent must be on the same desktop */ - if (parent && parent->desktop != desktop) - { - set_error( STATUS_ACCESS_DENIED ); - goto failed; - } - - /* if no parent, class must be the desktop */ - if (!parent && !is_desktop_class( class )) - { - set_error( STATUS_ACCESS_DENIED ); - goto failed; - } - /* if parent belongs to a different thread and the window isn't */ /* top-level, attach the two threads */ if (parent && parent->thread && parent->thread != current && !is_desktop_window(parent)) @@ -498,9 +507,17 @@ static struct window *create_window( struct window *parent, struct window *owner else { list_init( &win->entry ); - assert( !desktop->top_window ); - desktop->top_window = win; - set_process_default_desktop( current->process, desktop, current->desktop ); + if (is_desktop_class( class )) + { + assert( !desktop->top_window ); + desktop->top_window = win; + set_process_default_desktop( current->process, desktop, current->desktop ); + } + else + { + assert( !desktop->msg_window ); + desktop->msg_window = win; + } } current->desktop_users++; @@ -532,21 +549,13 @@ void destroy_thread_windows( struct thread *thread ) } /* get the desktop window */ -static struct window *get_desktop_window( struct thread *thread, int create ) +static struct window *get_desktop_window( struct thread *thread ) { struct window *top_window; struct desktop *desktop = get_thread_desktop( thread, 0 ); if (!desktop) return NULL; - - if (!(top_window = desktop->top_window) && create) - { - if ((top_window = create_window( NULL, NULL, DESKTOP_ATOM, 0 ))) - { - detach_window_thread( top_window ); - top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - } - } + top_window = desktop->top_window; release_object( desktop ); return top_window; } @@ -595,7 +604,7 @@ static inline void inc_window_paint_count( struct window *win, int incr ) /* check if window and all its ancestors are visible */ static int is_visible( const struct window *win ) { - while (win && win->parent) + while (win) { if (!(win->style & WS_VISIBLE)) return 0; win = win->parent; @@ -630,6 +639,29 @@ static inline int is_point_in_window( struct window *win, int x, int y ) return 1; } +/* fill an array with the handles of the children of a specified window */ +static unsigned int get_children_windows( struct window *parent, atom_t atom, thread_id_t tid, + user_handle_t *handles, unsigned int max_count ) +{ + struct window *ptr; + unsigned int count = 0; + + if (!parent) return 0; + + LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry ) + { + if (atom && get_class_atom(ptr->class) != atom) continue; + if (tid && get_thread_id(ptr->thread) != tid) continue; + if (handles) + { + if (count >= max_count) break; + handles[count] = ptr->handle; + } + count++; + } + return count; +} + /* find child of 'parent' that contains the given point (in parent-relative coords) */ static struct window *child_window_from_point( struct window *parent, int x, int y ) { @@ -769,7 +801,7 @@ static struct window *find_child_to_repaint( struct window *parent, struct threa /* find a window that needs to receive a WM_PAINT; also clear its internal paint flag */ user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread ) { - struct window *ptr, *win, *top_window = get_desktop_window( thread, 0 ); + struct window *ptr, *win, *top_window = get_desktop_window( thread ); if (!top_window) return 0; @@ -1708,19 +1740,18 @@ static void set_window_region( struct window *win, struct region *region, int re /* create a window */ DECL_HANDLER(create_window) { - struct window *win, *parent, *owner = NULL; + struct window *win, *parent = NULL, *owner = NULL; + struct unicode_str cls_name; atom_t atom; reply->handle = 0; - - if (!req->parent) parent = get_desktop_window( current, 0 ); - else if (!(parent = get_window( req->parent ))) return; + if (req->parent && !(parent = get_window( req->parent ))) return; if (req->owner) { if (!(owner = get_window( req->owner ))) return; if (is_desktop_window(owner)) owner = NULL; - else if (!is_desktop_window(parent)) + else if (parent && !is_desktop_window(parent)) { /* an owned window must be created as top-level */ set_error( STATUS_ACCESS_DENIED ); @@ -1730,10 +1761,8 @@ DECL_HANDLER(create_window) while (!is_desktop_window(owner->parent)) owner = owner->parent; } - if (get_req_data_size()) - atom = find_global_atom( NULL, get_req_data(), get_req_data_size() / sizeof(WCHAR) ); - else - atom = req->atom; + get_req_unicode_str( &cls_name ); + atom = cls_name.len ? find_global_atom( NULL, &cls_name ) : req->atom; if (!(win = create_window( parent, owner, atom, req->instance ))) return; @@ -1780,9 +1809,34 @@ DECL_HANDLER(destroy_window) /* retrieve the desktop window for the current thread */ DECL_HANDLER(get_desktop_window) { - struct window *win = get_desktop_window( current, req->force ); + struct desktop *desktop = get_thread_desktop( current, 0 ); + + if (!desktop) return; + + if (!desktop->top_window && req->force) /* create it */ + { + if ((desktop->top_window = create_window( NULL, NULL, DESKTOP_ATOM, 0 ))) + { + detach_window_thread( desktop->top_window ); + desktop->top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + } + } - if (win) reply->handle = win->handle; + if (!desktop->msg_window && req->force) /* create it */ + { + static const WCHAR messageW[] = {'M','e','s','s','a','g','e'}; + static const struct unicode_str name = { messageW, sizeof(messageW) }; + atom_t atom = add_global_atom( NULL, &name ); + if (atom && (desktop->msg_window = create_window( NULL, NULL, atom, 0 ))) + { + detach_window_thread( desktop->msg_window ); + desktop->msg_window->style = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + } + } + + reply->top_window = desktop->top_window ? desktop->top_window->handle : 0; + reply->msg_window = desktop->msg_window ? desktop->msg_window->handle : 0; + release_object( desktop ); } @@ -1901,48 +1955,51 @@ DECL_HANDLER(get_window_parents) /* get a list of the window children */ DECL_HANDLER(get_window_children) { - struct window *ptr, *parent; - int total = 0; + struct window *parent = NULL; + unsigned int total; user_handle_t *data; data_size_t len; + struct unicode_str cls_name; atom_t atom = req->atom; + struct desktop *desktop = NULL; + + get_req_unicode_str( &cls_name ); + if (cls_name.len && !(atom = find_global_atom( NULL, &cls_name ))) return; if (req->desktop) { - struct desktop *desktop = get_desktop_obj( current->process, req->desktop, DESKTOP_ENUMERATE ); - if (!desktop) return; + if (!(desktop = get_desktop_obj( current->process, req->desktop, DESKTOP_ENUMERATE ))) return; parent = desktop->top_window; - release_object( desktop ); } - else parent = get_window( req->parent ); - - if (!parent) return; - - if (get_req_data_size()) + else { - atom = find_global_atom( NULL, get_req_data(), get_req_data_size() / sizeof(WCHAR) ); - if (!atom) return; + if (req->parent && !(parent = get_window( req->parent ))) return; + if (!parent && !(desktop = get_thread_desktop( current, 0 ))) return; } - LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry ) - { - if (atom && get_class_atom(ptr->class) != atom) continue; - if (req->tid && get_thread_id(ptr->thread) != req->tid) continue; - total++; - } + if (parent) + total = get_children_windows( parent, atom, req->tid, NULL, 0 ); + else + total = get_children_windows( desktop->top_window, atom, req->tid, NULL, 0 ) + + get_children_windows( desktop->msg_window, atom, req->tid, NULL, 0 ); + reply->count = total; len = min( get_reply_max_size(), total * sizeof(user_handle_t) ); if (len && ((data = set_reply_data_size( len )))) { - LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry ) + if (parent) get_children_windows( parent, atom, req->tid, data, len / sizeof(user_handle_t) ); + else { - if (len < sizeof(*data)) break; - if (atom && get_class_atom(ptr->class) != atom) continue; - if (req->tid && get_thread_id(ptr->thread) != req->tid) continue; - *data++ = ptr->handle; - len -= sizeof(*data); + total = get_children_windows( desktop->top_window, atom, req->tid, + data, len / sizeof(user_handle_t) ); + data += total; + len -= total * sizeof(user_handle_t); + if (len >= sizeof(user_handle_t)) + get_children_windows( desktop->msg_window, atom, req->tid, + data, len / sizeof(user_handle_t) ); } } + if (desktop) release_object( desktop ); } @@ -2336,13 +2393,15 @@ DECL_HANDLER(redraw_window) /* set a window property */ DECL_HANDLER(set_window_property) { + struct unicode_str name; struct window *win = get_window( req->window ); if (!win) return; - if (get_req_data_size()) + get_req_unicode_str( &name ); + if (name.len) { - atom_t atom = add_global_atom( NULL, get_req_data(), get_req_data_size() / sizeof(WCHAR) ); + atom_t atom = add_global_atom( NULL, &name ); if (atom) { set_property( win, atom, req->handle, PROP_TYPE_STRING ); @@ -2356,13 +2415,13 @@ DECL_HANDLER(set_window_property) /* remove a window property */ DECL_HANDLER(remove_window_property) { + struct unicode_str name; struct window *win = get_window( req->window ); + get_req_unicode_str( &name ); if (win) { - atom_t atom = req->atom; - if (get_req_data_size()) atom = find_global_atom( NULL, get_req_data(), - get_req_data_size() / sizeof(WCHAR) ); + atom_t atom = name.len ? find_global_atom( NULL, &name ) : req->atom; if (atom) reply->handle = remove_property( win, atom ); } } @@ -2371,13 +2430,13 @@ DECL_HANDLER(remove_window_property) /* get a window property */ DECL_HANDLER(get_window_property) { + struct unicode_str name; struct window *win = get_window( req->window ); + get_req_unicode_str( &name ); if (win) { - atom_t atom = req->atom; - if (get_req_data_size()) atom = find_global_atom( NULL, get_req_data(), - get_req_data_size() / sizeof(WCHAR) ); + atom_t atom = name.len ? find_global_atom( NULL, &name ) : req->atom; if (atom) reply->handle = get_property( win, atom ); } } diff --git a/server/winstation.c b/server/winstation.c index 2ad41465df7..cfff0a4e434 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -227,6 +227,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned desktop->flags = flags; desktop->winstation = (struct winstation *)grab_object( winstation ); desktop->top_window = NULL; + desktop->msg_window = NULL; desktop->global_hooks = NULL; desktop->close_timeout = NULL; desktop->users = 0; @@ -270,6 +271,7 @@ static void desktop_destroy( struct object *obj ) struct desktop *desktop = (struct desktop *)obj; if (desktop->top_window) destroy_window( desktop->top_window ); + if (desktop->msg_window) destroy_window( desktop->msg_window ); if (desktop->global_hooks) release_object( desktop->global_hooks ); if (desktop->close_timeout) remove_timeout_user( desktop->close_timeout ); list_remove( &desktop->entry ); diff --git a/tools/c2man.pl b/tools/c2man.pl index dfd18774354..30c2186c148 100755 --- a/tools/c2man.pl +++ b/tools/c2man.pl @@ -90,14 +90,15 @@ sub process_extra_comment($); sub process_spec_file($) { my $spec_name = shift; - my $dll_name = $spec_name; - $dll_name =~ s/\..*//; # Strip the file extension + my ($dll_name, $dll_ext) = split(/\./, $spec_name); + $dll_ext = "dll" if ( $dll_ext eq "spec" ); my $uc_dll_name = uc $dll_name; my $spec_details = { NAME => $spec_name, DLL_NAME => $dll_name, + DLL_EXT => $dll_ext, NUM_EXPORTS => 0, NUM_STUBS => 0, NUM_FUNCS => 0, @@ -227,6 +228,7 @@ sub process_source_file($) COMMENT_NAME => "", ALT_NAME => "", DLL_NAME => "", + DLL_EXT => "", ORDINAL => "", RETURNS => "", PROTOTYPE => [], @@ -1095,7 +1097,7 @@ sub output_spec($) my $comment = { FILE => $spec_details->{DLL_NAME}, - COMMENT_NAME => $spec_details->{DLL_NAME}.".dll", + COMMENT_NAME => $spec_details->{DLL_NAME}.".".$spec_details->{DLL_EXT}, ALT_NAME => $spec_details->{DLL_NAME}, DLL_NAME => "", ORDINAL => "", diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 6846368c006..bb54b435cab 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -874,8 +874,8 @@ coclass_int: m_attributes interfacedec { $$ = make_ifref($2); $$->attrs = $1; } ; -dispinterface: tDISPINTERFACE aIDENTIFIER { $$ = get_type(0, $2, 0); $$->kind = TKIND_DISPATCH; } - | tDISPINTERFACE aKNOWNTYPE { $$ = get_type(0, $2, 0); $$->kind = TKIND_DISPATCH; } +dispinterface: tDISPINTERFACE aIDENTIFIER { $$ = get_type(RPC_FC_IP, $2, 0); $$->kind = TKIND_DISPATCH; } + | tDISPINTERFACE aKNOWNTYPE { $$ = get_type(RPC_FC_IP, $2, 0); $$->kind = TKIND_DISPATCH; } ; dispinterfacehdr: attributes dispinterface { attr_t *attrs; @@ -1479,6 +1479,14 @@ static void set_type(var_t *v, decl_spec_t *decl_spec, const declarator_t *decl, error_loc("'%s': [string] attribute applied to non-pointer, non-array type\n", v->name); + if (is_attr(v->attrs, ATTR_V1ENUM)) + { + if (v->type->type == RPC_FC_ENUM16) + v->type->type = RPC_FC_ENUM32; + else + error_loc("'%s': [v1_enum] attribute applied to non-enum type\n", v->name); + } + sizeless = FALSE; if (arr) LIST_FOR_EACH_ENTRY_REV(dim, arr, expr_t, entry) { @@ -1900,16 +1908,22 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at return type; } -type_t *find_type(const char *name, int t) +static type_t *find_type_helper(const char *name, int t) { struct rtype *cur = type_hash[hash_ident(name)]; while (cur && (cur->t != t || strcmp(cur->name, name))) cur = cur->next; - if (!cur) { + return cur ? cur->type : NULL; +} + +type_t *find_type(const char *name, int t) +{ + type_t *type = find_type_helper(name, t); + if (!type) { error_loc("type '%s' not found\n", name); return NULL; } - return cur->type; + return type; } static type_t *find_type2(char *name, int t) @@ -1921,25 +1935,18 @@ static type_t *find_type2(char *name, int t) int is_type(const char *name) { - struct rtype *cur = type_hash[hash_ident(name)]; - while (cur && (cur->t || strcmp(cur->name, name))) - cur = cur->next; - if (cur) return TRUE; - return FALSE; + return find_type_helper(name, 0) != NULL; } static type_t *get_type(unsigned char type, char *name, int t) { - struct rtype *cur = NULL; type_t *tp; if (name) { - cur = type_hash[hash_ident(name)]; - while (cur && (cur->t != t || strcmp(cur->name, name))) - cur = cur->next; - } - if (cur) { - free(name); - return cur->type; + tp = find_type_helper(name, t); + if (tp) { + free(name); + return tp; + } } tp = make_type(type, NULL); tp->name = name; @@ -2253,7 +2260,7 @@ struct allowed_attr allowed_attr[] = /* ATTR_CONST */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "const" }, /* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "context_handle" }, /* ATTR_CONTROL */ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, "control" }, - /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, "default" }, + /* ATTR_DEFAULT */ { 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, "default" }, /* ATTR_DEFAULTCOLLELEM */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "defaultcollelem" }, /* ATTR_DEFAULTVALUE */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "defaultvalue" }, /* ATTR_DEFAULTVTABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "defaultvtable" }, @@ -2616,7 +2623,7 @@ static void check_remoting_fields(const var_t *var, type_t *type) fields = type->fields_or_args; } - if (fields) LIST_FOR_EACH_ENTRY( field, type->fields_or_args, const var_t, entry ) + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) if (field->type) check_field_common(type, type->name, field); } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 41134d803c7..f89f13fb9b8 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -41,6 +41,11 @@ #include "typegen.h" #include "expr.h" +/* round size up to multiple of alignment */ +#define ROUND_SIZE(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1)) +/* value to add on to round size up to a multiple of alignment */ +#define ROUNDING(size, alignment) (((alignment) - 1) - (((size) + ((alignment) - 1)) & ((alignment) - 1))) + static const func_t *current_func; static const type_t *current_structure; static const type_t *current_iface; @@ -754,11 +759,11 @@ static size_t fields_memsize(const var_list_t *fields, unsigned int *align) *align = falign; have_align = TRUE; } - size = (size + (falign - 1)) & ~(falign - 1); + size = ROUND_SIZE(size, falign); size += fsize; } - size = (size + (*align - 1)) & ~(*align - 1); + size = ROUND_SIZE(size, *align); return size; } @@ -798,18 +803,20 @@ int get_padding(const var_list_t *fields) size_t size = type_memsize(ft, &align); if (salign == -1) salign = align; - offset = (offset + (align - 1)) & ~(align - 1); + offset = ROUND_SIZE(offset, align); offset += size; } - return ((offset + (salign - 1)) & ~(salign - 1)) - offset; + return ROUNDING(offset, salign); } size_t type_memsize(const type_t *t, unsigned int *align) { size_t size = 0; - if (t->declarray && is_conformant_array(t)) + if (t->kind == TKIND_ALIAS) + size = type_memsize(t->orig, align); + else if (t->declarray && is_conformant_array(t)) { type_memsize(t->ref, align); size = 0; @@ -1112,6 +1119,8 @@ static int write_no_repeat_pointer_descriptions( if (is_ptr(type) || (!type->declarray && is_conformant_array(type))) { + size_t memsize; + print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT); print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD); @@ -1139,10 +1148,11 @@ static int write_no_repeat_pointer_descriptions( } align = 0; - *offset_in_memory += type_memsize(type, &align); - /* FIXME: is there a case where these two are different? */ - align = 0; - *offset_in_buffer += type_memsize(type, &align); + memsize = type_memsize(type, &align); + *offset_in_memory += memsize; + /* increment these separately as in the case of conformant (varying) + * structures these start at different values */ + *offset_in_buffer += memsize; return 1; } @@ -1151,17 +1161,30 @@ static int write_no_repeat_pointer_descriptions( { const var_t *v; LIST_FOR_EACH_ENTRY( v, type->fields_or_args, const var_t, entry ) + { + if (offset_in_memory && offset_in_buffer) + { + size_t padding; + align = 0; + type_memsize(v->type, &align); + padding = ROUNDING(*offset_in_memory, align); + *offset_in_memory += padding; + *offset_in_buffer += padding; + } written += write_no_repeat_pointer_descriptions( file, v->type, offset_in_memory, offset_in_buffer, typestring_offset); + } } else { + size_t memsize; align = 0; - *offset_in_memory += type_memsize(type, &align); - /* FIXME: is there a case where these two are different? */ - align = 0; - *offset_in_buffer += type_memsize(type, &align); + memsize = type_memsize(type, &align); + *offset_in_memory += memsize; + /* increment these separately as in the case of conformant (varying) + * structures these start at different values */ + *offset_in_buffer += memsize; } return written; @@ -1179,16 +1202,19 @@ static int write_pointer_description_offsets( { if (offset_in_memory && offset_in_buffer) { + size_t memsize; + /* pointer instance */ /* FIXME: sometimes from end of structure, sometimes from beginning */ print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory); print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer); align = 0; - *offset_in_memory += type_memsize(type, &align); - /* FIXME: is there a case where these two are different? */ - align = 0; - *offset_in_buffer += type_memsize(type, &align); + memsize = type_memsize(type, &align); + *offset_in_memory += memsize; + /* increment these separately as in the case of conformant (varying) + * structures these start at different values */ + *offset_in_buffer += memsize; } *typestring_offset += 4; @@ -1206,7 +1232,7 @@ static int write_pointer_description_offsets( { return write_pointer_description_offsets( file, attrs, type->ref, offset_in_memory, offset_in_buffer, - typestring_offset); + typestring_offset); } else if (is_non_complex_struct(type)) { @@ -1214,6 +1240,15 @@ static int write_pointer_description_offsets( const var_t *v; LIST_FOR_EACH_ENTRY( v, type->fields_or_args, const var_t, entry ) { + if (offset_in_memory && offset_in_buffer) + { + size_t padding; + align = 0; + type_memsize(v->type, &align); + padding = ROUNDING(*offset_in_memory, align); + *offset_in_memory += padding; + *offset_in_buffer += padding; + } written += write_pointer_description_offsets( file, v->attrs, v->type, offset_in_memory, offset_in_buffer, typestring_offset); @@ -1221,13 +1256,16 @@ static int write_pointer_description_offsets( } else { - align = 0; - if (offset_in_memory) - *offset_in_memory += type_memsize(type, &align); - /* FIXME: is there a case where these two are different? */ - align = 0; - if (offset_in_buffer) - *offset_in_buffer += type_memsize(type, &align); + if (offset_in_memory && offset_in_buffer) + { + size_t memsize; + align = 0; + memsize = type_memsize(type, &align); + *offset_in_memory += memsize; + /* increment these separately as in the case of conformant (varying) + * structures these start at different values */ + *offset_in_buffer += memsize; + } } return written; @@ -1277,6 +1315,15 @@ static int write_fixed_array_pointer_descriptions( const var_t *v; LIST_FOR_EACH_ENTRY( v, type->fields_or_args, const var_t, entry ) { + if (offset_in_memory && offset_in_buffer) + { + size_t padding; + align = 0; + type_memsize(v->type, &align); + padding = ROUNDING(*offset_in_memory, align); + *offset_in_memory += padding; + *offset_in_buffer += padding; + } pointer_count += write_fixed_array_pointer_descriptions( file, v->attrs, v->type, offset_in_memory, offset_in_buffer, typestring_offset); @@ -1284,13 +1331,16 @@ static int write_fixed_array_pointer_descriptions( } else { - align = 0; - if (offset_in_memory) - *offset_in_memory += type_memsize(type, &align); - /* FIXME: is there a case where these two are different? */ - align = 0; - if (offset_in_buffer) - *offset_in_buffer += type_memsize(type, &align); + if (offset_in_memory && offset_in_buffer) + { + size_t memsize; + align = 0; + memsize = type_memsize(type, &align); + *offset_in_memory += memsize; + /* increment these separately as in the case of conformant (varying) + * structures these start at different values */ + *offset_in_buffer += memsize; + } } return pointer_count; @@ -1350,8 +1400,6 @@ static int write_varying_array_pointer_descriptions( unsigned int align; int pointer_count = 0; - /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */ - if (is_array(type) && type->length_is) { unsigned int temp = 0; @@ -1362,8 +1410,6 @@ static int write_varying_array_pointer_descriptions( if (pointer_count > 0) { unsigned int increment_size; - size_t offset_of_array_pointer_mem = 0; - size_t offset_of_array_pointer_buf = 0; align = 0; increment_size = type_memsize(type->ref, &align); @@ -1379,8 +1425,8 @@ static int write_varying_array_pointer_descriptions( *typestring_offset += 8; pointer_count = write_pointer_description_offsets( - file, attrs, type, &offset_of_array_pointer_mem, - &offset_of_array_pointer_buf, typestring_offset); + file, attrs, type, offset_in_memory, + offset_in_buffer, typestring_offset); } } else if (is_struct(type->type)) @@ -1388,6 +1434,15 @@ static int write_varying_array_pointer_descriptions( const var_t *v; LIST_FOR_EACH_ENTRY( v, type->fields_or_args, const var_t, entry ) { + if (offset_in_memory && offset_in_buffer) + { + size_t padding; + align = 0; + type_memsize(v->type, &align); + padding = ROUNDING(*offset_in_memory, align); + *offset_in_memory += padding; + *offset_in_buffer += padding; + } pointer_count += write_varying_array_pointer_descriptions( file, v->attrs, v->type, offset_in_memory, offset_in_buffer, typestring_offset); @@ -1395,13 +1450,16 @@ static int write_varying_array_pointer_descriptions( } else { - align = 0; - if (offset_in_memory) - *offset_in_memory += type_memsize(type, &align); - /* FIXME: is there a case where these two are different? */ - align = 0; - if (offset_in_buffer) - *offset_in_buffer += type_memsize(type, &align); + if (offset_in_memory && offset_in_buffer) + { + size_t memsize; + align = 0; + memsize = type_memsize(type, &align); + *offset_in_memory += memsize; + /* increment these separately as in the case of conformant (varying) + * structures these start at different values */ + *offset_in_buffer += memsize; + } } return pointer_count; @@ -1412,13 +1470,19 @@ static void write_pointer_description(FILE *file, type_t *type, { size_t offset_in_buffer; size_t offset_in_memory; + size_t conformance = 0; + + if (type->type == RPC_FC_CVSTRUCT) + conformance = 8; + else if (type->type == RPC_FC_CSTRUCT || type->type == RPC_FC_CPSTRUCT) + conformance = 4; /* pass 1: search for single instance of a pointer (i.e. don't descend * into arrays) */ if (!is_array(type)) { offset_in_memory = 0; - offset_in_buffer = 0; + offset_in_buffer = conformance; write_no_repeat_pointer_descriptions( file, type, &offset_in_memory, &offset_in_buffer, typestring_offset); @@ -1426,7 +1490,7 @@ static void write_pointer_description(FILE *file, type_t *type, /* pass 2: search for pointers in fixed arrays */ offset_in_memory = 0; - offset_in_buffer = 0; + offset_in_buffer = conformance; write_fixed_array_pointer_descriptions( file, NULL, type, &offset_in_memory, &offset_in_buffer, typestring_offset); @@ -1446,9 +1510,9 @@ static void write_pointer_description(FILE *file, type_t *type, typestring_offset); } - /* pass 4: search for pointers in varying arrays */ + /* pass 4: search for pointers in varying arrays */ offset_in_memory = 0; - offset_in_buffer = 0; + offset_in_buffer = conformance; write_varying_array_pointer_descriptions( file, NULL, type, &offset_in_memory, &offset_in_buffer, typestring_offset); @@ -1659,14 +1723,20 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type static const var_t *find_array_or_string_in_struct(const type_t *type) { - const var_t *last_field = LIST_ENTRY( list_tail(type->fields_or_args), const var_t, entry ); - const type_t *ft = last_field->type; + const var_t *last_field; + const type_t *ft; + + if (!type->fields_or_args || list_empty(type->fields_or_args)) + return NULL; + + last_field = LIST_ENTRY( list_tail(type->fields_or_args), const var_t, entry ); + ft = last_field->type; if (ft->declarray && is_conformant_array(ft)) return last_field; if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT) - return find_array_or_string_in_struct(last_field->type); + return find_array_or_string_in_struct(ft); else return NULL; } @@ -1703,7 +1773,7 @@ static void write_struct_members(FILE *file, const type_t *type, error("write_struct_members: cannot align type %d\n", ft->type); } print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); - offset = (offset + (align - 1)) & ~(align - 1); + offset = ROUND_SIZE(offset, align); *typestring_offset += 1; } write_member_type(file, type, field->attrs, field->type, corroff, @@ -1712,7 +1782,7 @@ static void write_struct_members(FILE *file, const type_t *type, } } - padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset; + padding = ROUNDING(offset, salign); if (padding) { print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n", diff --git a/tools/wine.desktop b/tools/wine.desktop index 2be9b53ad0e..fe8f1e30851 100644 --- a/tools/wine.desktop +++ b/tools/wine.desktop @@ -1,12 +1,20 @@ [Desktop Entry] Type=Application -Name=Wine Windows Emulator -Name[de]=Wine Windows-Emulator -Name[es]=Emulador Windows de Wine -Name[nl]=Wine Windows-emulator -Name[sv]=Windows-emulatorn Wine -Name[ru]=Wine Эмулятор Windows -Name[fr]=Émulateur Windows Wine +Name=Wine Windows Program Loader +Name[de]=Wine Windows-Programmstarter +Name[es]=Wine Cargador de programas de Windows +Name[nl]=Wine Windows programmalader +Name[sv]=Wine Windows Programstartare +Name[ru]=Wine - загрузчик Windows программ +Name[uk]=Wine - завантажувач Windows програм +Name[fr]=Wine Exécuter des programmes Windows +Name[ca]=Wine - Carregador d'aplicacions del Windows +Name[pt]=Carregador de aplicativos Windows Wine +Name[pt_br]=Carregador de aplicativos Windows Wine +Name[it]=Wine Carica Programmi Windows +Name[da]=Wine, Programstarter til Windows-programmer +Name[nb]=Wine Programlaster for Windowsapplikasjoner +Name[nn]=Wine Programlaster for Windowsapplikasjoner Exec=wine start /unix %f -MimeType=application/x-ms-dos-executable;application/x-msdos-program;application/x-msdownload;application/exe;application/x-exe;application/dos-exe;vms/exe;application/x-winexe;application/msdos-windows;application/x-zip-compressed;application/x-executable; +MimeType=application/x-ms-dos-executable;application/x-msdos-program;application/x-msdownload;application/exe;application/x-exe;application/dos-exe;vms/exe;application/x-winexe;application/msdos-windows;application/x-zip-compressed;application/x-executable;application/x-msi; NoDisplay=true diff --git a/tools/wine.inf.in b/tools/wine.inf.in index 251f70662b8..3e3a62528ab 100644 --- a/tools/wine.inf.in +++ b/tools/wine.inf.in @@ -96,6 +96,7 @@ Control="System\CurrentControlSet\Control" [Classes] HKCR,.avi,"Content Type",2,"video/avi" HKCR,.chm,,2,"chm.file" +HKCR,.cpl,,2,"cplfile" HKCR,.dll,"Content Type",2,"application/x-msdownload" HKCR,.exe,,2,"exefile" HKCR,.exe,"Content Type",2,"application/x-msdownload" @@ -119,6 +120,8 @@ HKCR,.xml,,2,"xmlfile" HKCR,.xml,"Content Type",2,"text/xml" HKCR,.xsl,"Content Type",2,"text/xsl" HKCR,chm.file\shell\open\command,,2,"%11%\hh.exe %1" +HKCR,cplfile\shell\cplopen,,2,"Open with Control Panel" +HKCR,cplfile\shell\cplopen\command,,2,"rundll32.exe shell32.dll,Control_RunDLL ""%1"",%*" HKCR,exefile\DefaultIcon,,2,"%1" HKCR,exefile\shell\open\command,,2,"""%1"" %*" HKCR,folder\shell\open\ddeexec,,2,"[ViewFolder("%l", %I, %S)]" @@ -196,16 +199,16 @@ HKLM,%CurrentVersion%,"FirstInstallDateTime",1,21,81,7c,23 HKLM,%CurrentVersion%,"ProductId",,"12345-oem-0000001-54321" HKLM,%CurrentVersion%,"ProgramFilesDir",,"%16422%" HKLM,%CurrentVersion%,"ProgramFilesPath",0x20000,"%%ProgramFiles%%" -HKLM,%CurrentVersion%,"RegisteredOrganization",2,"Change preferred organization in ~/.wine/system.reg" -HKLM,%CurrentVersion%,"RegisteredOwner",2,"Change preferred owner in ~/.wine/system.reg" +HKLM,%CurrentVersion%,"RegisteredOrganization",2,"" +HKLM,%CurrentVersion%,"RegisteredOwner",2,"" HKLM,%CurrentVersion%\Controls Folder\PowerCfg,"DiskSpinDownMax",,"3600" HKLM,%CurrentVersion%\Controls Folder\PowerCfg,"DiskSpinDownMin",,"3" HKLM,%CurrentVersion%\Controls Folder\PowerCfg,"LastID",,"5" HKLM,%CurrentVersion%\Setup,"BootDir",,"%30%" HKLM,%CurrentVersion%\Setup,"SharedDir",,"%25%" HKLM,%CurrentVersion%\Uninstall,,,"" -HKLM,%CurrentVersionNT%,"RegisteredOrganization",2,"Change preferred organization in ~/.wine/system.reg" -HKLM,%CurrentVersionNT%,"RegisteredOwner",2,"Change preferred owner in ~/.wine/system.reg" +HKLM,%CurrentVersionNT%,"RegisteredOrganization",2,"" +HKLM,%CurrentVersionNT%,"RegisteredOwner",2,"" HKLM,%CurrentVersionNT%,"SystemRoot",,"%10%" HKLM,%CurrentVersionNT%\Fonts,,,"" HKLM,%CurrentVersionNT%\Q246009,"Installed",,"1" @@ -281,10 +284,12 @@ HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"windir",0x000 HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"winsysdir",,"%11%" [Fonts] +HKLM,%FontSubStr%,"Arial Baltic,186",,"Arial,186" HKLM,%FontSubStr%,"Arial CE,238",,"Arial,238" HKLM,%FontSubStr%,"Arial CYR,204",,"Arial,204" HKLM,%FontSubStr%,"Arial Greek,161",,"Arial,161" HKLM,%FontSubStr%,"Arial TUR,162",,"Arial,162" +HKLM,%FontSubStr%,"Courier New Baltic,186",,"Courier New,186" HKLM,%FontSubStr%,"Courier New CE,238",,"Courier New,238" HKLM,%FontSubStr%,"Courier New CYR,204",,"Courier New,204" HKLM,%FontSubStr%,"Courier New Greek,161",,"Courier New,161" @@ -293,6 +298,7 @@ HKLM,%FontSubStr%,"Helv",,"MS Sans Serif" HKLM,%FontSubStr%,"Helvetica",,"Arial" HKLM,%FontSubStr%,"MS Shell Dlg 2",,"Tahoma" HKLM,%FontSubStr%,"Times",,"Times New Roman" +HKLM,%FontSubStr%,"Times New Roman Baltic,186",,"Times New Roman,186" HKLM,%FontSubStr%,"Times New Roman CE,238",,"Times New Roman,238" HKLM,%FontSubStr%,"Times New Roman CYR,204",,"Times New Roman,204" HKLM,%FontSubStr%,"Times New Roman Greek,161",,"Times New Roman,161" diff --git a/tools/winegcc/Makefile.in b/tools/winegcc/Makefile.in index 31c3a5ba6a2..fd7691ddea1 100644 --- a/tools/winegcc/Makefile.in +++ b/tools/winegcc/Makefile.in @@ -9,6 +9,7 @@ DEFS = \ -DCPP="\"@CPPBIN@\"" \ -DCXX="\"@CXX@\"" \ -DLD="\"$(LD)\"" \ + -DNM="\"$(NM)\"" \ -DPRELINK="\"$(PRELINK)\"" TOPSRCDIR = @top_srcdir@ diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index 2c63ae564c5..b4a314df3aa 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -572,6 +572,8 @@ static void build(struct options* opts) strarray_add(spec_args, AS); strarray_add(spec_args, "--ld-cmd"); strarray_add(spec_args, LD); + strarray_add(spec_args, "--nm-cmd"); + strarray_add(spec_args, NM); strarray_addall(spec_args, strarray_fromstring(DLLFLAGS, " ")); strarray_add(spec_args, opts->shared ? "--dll" : "--exe"); strarray_add(spec_args, "-o"); -- 2.11.4.GIT