From 88f91216b62b9385b1c27ada3d940823d49d127b Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Sat, 2 Aug 2008 20:10:55 +0200 Subject: [PATCH] push 5b66f3b36e7323272378316c923222b908f6e2d3 --- Makefile.in | 2 + configure | 7 +- configure.ac | 5 +- dlls/Makefile.in | 1 + dlls/advapi32/cred.c | 1 - dlls/advapi32/tests/registry.c | 21 +- dlls/appwiz.cpl/En.rc | 3 +- dlls/appwiz.cpl/appwiz.c | 98 +- dlls/appwiz.cpl/appwiz.cpl.spec | 2 +- dlls/appwiz.cpl/res.h | 1 + dlls/browseui/progressdlg.c | 2 +- dlls/comctl32/imagelist.c | 6 +- dlls/comctl32/tests/comboex.c | 9 +- dlls/comctl32/updown.c | 35 +- dlls/comdlg32/fontdlg.c | 2 +- dlls/crypt32/Makefile.in | 1 + dlls/crypt32/crypt32.spec | 2 +- dlls/crypt32/message.c | 270 ++++ dlls/crypt32/msg.c | 167 --- dlls/crypt32/sip.c | 2 +- dlls/crypt32/tests/Makefile.in | 1 + dlls/crypt32/tests/cert.c | 77 +- dlls/crypt32/tests/chain.c | 17 + dlls/crypt32/tests/message.c | 409 ++++++ dlls/crypt32/tests/msg.c | 231 +--- dlls/crypt32/tests/sip.c | 60 +- dlls/d3dx8/mesh.c | 5 +- dlls/d3dx8/tests/mesh.c | 4 + dlls/d3dx9_36/Makefile.in | 3 +- dlls/d3dx9_36/d3dx9_36.spec | 2 +- dlls/d3dx9_36/d3dx9_36_private.h | 17 +- dlls/d3dx9_36/font.c | 6 + dlls/d3dx9_36/sprite.c | 176 +++ dlls/d3dxof/main.c | 4 +- dlls/ddraw/device.c | 2 +- dlls/dinput/device.c | 4 +- dlls/dinput/device_private.h | 2 +- dlls/dinput/joystick_linux.c | 2 +- dlls/dinput/joystick_linuxinput.c | 33 +- dlls/dinput/keyboard.c | 2 +- dlls/dinput/mouse.c | 2 +- dlls/dinput/tests/keyboard.c | 18 +- dlls/dmband/dmutils.c | 3 +- dlls/dmcompos/dmcompos_main.c | 3 +- dlls/dmime/dmutils.c | 3 +- dlls/dmloader/debug.c | 3 +- dlls/dmscript/dmscript_main.c | 3 +- dlls/dmstyle/dmutils.c | 5 +- dlls/dmsynth/dmsynth_main.c | 3 +- dlls/dmusic/dmusic_main.c | 3 +- dlls/dnsapi/query.c | 5 +- dlls/dplayx/dplay.c | 27 +- dlls/dplayx/regsvr.c | 2 +- dlls/dplayx/tests/Makefile.in | 2 +- dlls/dplayx/tests/dplayx.c | 980 +++++++++++++-- dlls/dpnet/Makefile.in | 3 +- dlls/dpnet/dpnet_main.c | 1 + dlls/dpnet/dpnet_private.h | 12 + dlls/dpnet/threadpool.c | 143 +++ dlls/dswave/dswave_main.c | 3 +- dlls/gdi32/bitblt.c | 2 + dlls/gdi32/font.c | 10 +- dlls/gdi32/tests/font.c | 10 +- dlls/gdiplus/customlinecap.c | 41 +- dlls/gdiplus/font.c | 35 +- dlls/gdiplus/gdiplus.spec | 22 +- dlls/gdiplus/gdiplus_private.h | 8 + dlls/gdiplus/image.c | 22 + dlls/gdiplus/pen.c | 49 +- dlls/gdiplus/region.c | 8 +- dlls/gdiplus/stringformat.c | 133 +- dlls/gdiplus/tests/Makefile.in | 1 + dlls/gdiplus/tests/customlinecap.c | 202 +++ dlls/gdiplus/tests/font.c | 9 + dlls/gdiplus/tests/pen.c | 50 + dlls/gdiplus/tests/stringformat.c | 253 +++- dlls/inetmib1/main.c | 9 + dlls/kernel32/tests/codepage.c | 134 ++ dlls/kernel32/tests/profile.c | 13 +- dlls/kernel32/tests/sync.c | 113 +- dlls/mlang/tests/mlang.c | 173 +++ dlls/mscoree/mscoree.spec | 2 +- dlls/mshtml/htmlelem.c | 23 +- dlls/mshtml/htmlelem2.c | 66 +- dlls/mshtml/htmltextcont.c | 38 +- dlls/mshtml/omnavigator.c | 9 +- dlls/mshtml/tests/dom.c | 86 ++ dlls/mshtml/tests/protocol.c | 6 +- dlls/msi/action.c | 27 +- dlls/msi/msi.c | 180 ++- dlls/msi/msipriv.h | 2 + dlls/msi/registry.c | 34 + dlls/msi/tests/install.c | 156 +++ dlls/msi/tests/msi.c | 419 +++++++ dlls/{mstask => msisip}/Makefile.in | 10 +- dlls/msisip/main.c | 250 ++++ dlls/msisip/msisip.spec | 8 + dlls/mstask/Makefile.in | 2 + dlls/mstask/mstask.inf | 16 + dlls/mstask/mstask.spec | 2 + dlls/mstask/mstask_main.c | 103 ++ include/intshcut.h => dlls/mstask/rsrc.rc | 22 +- dlls/msxml3/Makefile.in | 1 + dlls/msxml3/bsc.c | 310 +++++ dlls/msxml3/domdoc.c | 299 +---- dlls/msxml3/main.c | 8 + dlls/msxml3/msxml_private.h | 5 + dlls/msxml3/node.c | 67 +- dlls/msxml3/saxreader.c | 1948 ++++++++++++++++++++++------- dlls/msxml3/tests/domdoc.c | 39 + dlls/msxml3/tests/saxreader.c | 15 + dlls/netapi32/access.c | 12 + dlls/netapi32/netapi32.spec | 4 +- dlls/netapi32/wksta.c | 13 + dlls/ntdll/signal_i386.c | 8 +- dlls/ntdll/threadpool.c | 50 +- dlls/ntoskrnl.exe/ntoskrnl.c | 39 + dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 8 +- dlls/ole32/defaulthandler.c | 2 +- dlls/oleaut32/typelib.c | 64 +- dlls/qcap/dllsetup.c | 122 +- dlls/qcap/dllsetup.h | 11 +- dlls/qcap/qcap_main.c | 13 - dlls/quartz/acmwrapper.c | 33 +- dlls/quartz/avidec.c | 18 +- dlls/quartz/avisplit.c | 30 +- dlls/quartz/memallocator.c | 34 +- dlls/quartz/transform.c | 49 +- dlls/quartz/transform.h | 15 +- dlls/quartz/videorenderer.c | 2 +- dlls/rasapi32/rasapi.c | 1 + dlls/rasapi32/tests/rasapi.c | 7 +- dlls/riched20/editor.c | 33 +- dlls/riched20/tests/editor.c | 85 +- dlls/rpcrt4/rpc_binding.c | 26 +- dlls/rpcrt4/rpc_epmap.c | 3 + dlls/rpcrt4/tests/rpc.c | 2 - dlls/rsaenh/rsaenh.c | 6 +- dlls/rsaenh/tests/rsaenh.c | 30 + dlls/secur32/tests/ntlm.c | 2 + dlls/secur32/tests/schannel.c | 2 +- dlls/shell32/autocomplete.c | 152 +-- dlls/shell32/control.c | 19 +- dlls/shell32/shell32_Ko.rc | 16 +- dlls/shell32/shell32_No.rc | 16 +- dlls/shell32/shell32_Ru.rc | 20 +- dlls/shell32/shellpath.c | 9 +- dlls/shell32/tests/shlexec.c | 3 + dlls/shell32/tests/shlfileop.c | 93 +- dlls/shlwapi/path.c | 13 +- dlls/shlwapi/tests/path.c | 2 +- dlls/user32/driver.c | 13 + dlls/user32/edit.c | 18 + dlls/user32/tests/dde.c | 2 +- dlls/user32/tests/dialog.c | 13 +- dlls/user32/tests/msg.c | 75 +- dlls/user32/tests/resource.c | 9 +- dlls/user32/user_private.h | 1 + dlls/user32/win.c | 3 +- dlls/user32/winpos.c | 16 +- dlls/wined3d/arb_program_shader.c | 983 +++++++++++++-- dlls/wined3d/ati_fragment_shader.c | 46 +- dlls/wined3d/context.c | 3 - dlls/wined3d/device.c | 16 +- dlls/wined3d/directx.c | 19 +- dlls/wined3d/drawprim.c | 42 +- dlls/wined3d/glsl_shader.c | 2 +- dlls/wined3d/surface_base.c | 191 +-- dlls/wined3d/utils.c | 230 +++- dlls/wined3d/wined3d_private.h | 58 +- dlls/winex11.drv/event.c | 92 +- dlls/winex11.drv/window.c | 42 + dlls/winex11.drv/winex11.drv.spec | 5 +- dlls/winhttp/main.c | 12 + dlls/winhttp/tests/winhttp.c | 73 ++ dlls/winhttp/winhttp.spec | 2 +- dlls/wininet/http.c | 7 +- dlls/wininet/tests/http.c | 30 + dlls/wininet/urlcache.c | 5 +- include/Makefile.in | 1 + include/ddk/wdm.h | 58 + include/dplay.h | 19 +- include/gdiplusenums.h | 9 + include/gdiplusflat.h | 15 + include/intshcut.h | 70 +- include/lmaccess.h | 1 + include/lmwksta.h | 1 + include/ras.h | 4 - include/{intshcut.h => raserror.h} | 23 +- include/uuids.h | 1 + include/wine/test.h | 11 +- include/winhttp.h | 1 + programs/cmd/wcmdmain.c | 16 + programs/taskmgr/Da.rc | 15 - programs/taskmgr/De.rc | 15 - programs/taskmgr/En.rc | 15 - programs/taskmgr/Fr.rc | 15 - programs/taskmgr/Ja.rc | 15 - programs/taskmgr/Ko.rc | 15 - programs/taskmgr/Nl.rc | 15 - programs/taskmgr/No.rc | 15 - programs/taskmgr/Pl.rc | 15 - programs/taskmgr/Ru.rc | 81 +- programs/taskmgr/Si.rc | 15 - programs/taskmgr/Tr.rc | 15 - programs/taskmgr/resource.h | 3 - programs/taskmgr/trayicon.c | 36 +- programs/winecfg/theme.c | 4 +- programs/winefile/winefile.c | 18 +- programs/winetest/main.c | 21 +- programs/winhlp32/Da.rc | 2 - programs/winhlp32/De.rc | 2 - programs/winhlp32/En.rc | 2 - programs/winhlp32/Fr.rc | 2 - programs/winhlp32/Ko.rc | 2 - programs/winhlp32/Nl.rc | 2 - programs/winhlp32/No.rc | 2 - programs/winhlp32/Pl.rc | 2 - programs/winhlp32/Ru.rc | 2 - programs/winhlp32/Si.rc | 2 - programs/winhlp32/winhelp.c | 6 - tools/wine.inf.in | 8 +- 222 files changed, 9300 insertions(+), 2735 deletions(-) create mode 100644 dlls/crypt32/message.c create mode 100644 dlls/crypt32/tests/message.c create mode 100644 dlls/d3dx9_36/sprite.c rewrite dlls/dplayx/tests/dplayx.c (66%) create mode 100644 dlls/dpnet/threadpool.c create mode 100644 dlls/gdiplus/tests/customlinecap.c copy dlls/{mstask => msisip}/Makefile.in (59%) create mode 100644 dlls/msisip/main.c create mode 100644 dlls/msisip/msisip.spec create mode 100644 dlls/mstask/mstask.inf copy include/intshcut.h => dlls/mstask/rsrc.rc (72%) create mode 100644 dlls/msxml3/bsc.c copy include/{intshcut.h => raserror.h} (70%) diff --git a/Makefile.in b/Makefile.in index bb1ec014d2d..3cd9452ec10 100644 --- a/Makefile.in +++ b/Makefile.in @@ -347,6 +347,7 @@ ALL_MAKEFILES = \ dlls/msi/tests/Makefile \ dlls/msimg32/Makefile \ dlls/msimtf/Makefile \ + dlls/msisip/Makefile \ dlls/msisys.ocx/Makefile \ dlls/msnet32/Makefile \ dlls/msrle32/Makefile \ @@ -780,6 +781,7 @@ dlls/msi/Makefile: dlls/msi/Makefile.in dlls/Makedll.rules dlls/msi/tests/Makefile: dlls/msi/tests/Makefile.in dlls/Maketest.rules dlls/msimg32/Makefile: dlls/msimg32/Makefile.in dlls/Makedll.rules dlls/msimtf/Makefile: dlls/msimtf/Makefile.in dlls/Makedll.rules +dlls/msisip/Makefile: dlls/msisip/Makefile.in dlls/Makedll.rules dlls/msisys.ocx/Makefile: dlls/msisys.ocx/Makefile.in dlls/Makedll.rules dlls/msnet32/Makefile: dlls/msnet32/Makefile.in dlls/Makedll.rules dlls/msrle32/Makefile: dlls/msrle32/Makefile.in dlls/Makedll.rules diff --git a/configure b/configure index 09e3267abec..0f543a041d1 100755 --- a/configure +++ b/configure @@ -15038,7 +15038,7 @@ if test "x$with_cups" != "xno" then ac_save_CPPFLAGS="$CPPFLAGS" ac_cups_cflags=`cups-config --cflags 2>/dev/null` - ac_cups_libs="`cups-config --ldflags 2>/dev/null` `cups-config --libs 2>/dev/null`" + ac_cups_libs=`cups-config --ldflags 2>/dev/null` CPPFLAGS="$CPPFLAGS $ac_cups_cflags" for ac_header in cups/cups.h @@ -16129,7 +16129,7 @@ _ACEOF fi -if test "x$ALSALIBS$AUDIOIOLIBS$COREAUDIO$NASLIBS$ESD_LIBS$ac_cv_lib_soname_jack" = "x" -a \ +if test "x$ALSALIBS$AUDIOIOLIBS$COREAUDIO$NASLIBS$ESDLIBS$ac_cv_lib_soname_jack" = "x" -a \ "$ac_cv_header_sys_soundcard_h" != "yes" -a \ "$ac_cv_header_machine_soundcard_h" != "yes" -a \ "$ac_cv_header_soundcard_h" != "yes" -a \ @@ -22294,6 +22294,8 @@ ac_config_files="$ac_config_files dlls/msimg32/Makefile" ac_config_files="$ac_config_files dlls/msimtf/Makefile" +ac_config_files="$ac_config_files dlls/msisip/Makefile" + ac_config_files="$ac_config_files dlls/msisys.ocx/Makefile" ac_config_files="$ac_config_files dlls/msnet32/Makefile" @@ -23515,6 +23517,7 @@ do "dlls/msi/tests/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/msi/tests/Makefile" ;; "dlls/msimg32/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/msimg32/Makefile" ;; "dlls/msimtf/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/msimtf/Makefile" ;; + "dlls/msisip/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/msisip/Makefile" ;; "dlls/msisys.ocx/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/msisys.ocx/Makefile" ;; "dlls/msnet32/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/msnet32/Makefile" ;; "dlls/msrle32/Makefile") CONFIG_FILES="$CONFIG_FILES dlls/msrle32/Makefile" ;; diff --git a/configure.ac b/configure.ac index 8dc6c5a3a7c..05dd286d7d6 100644 --- a/configure.ac +++ b/configure.ac @@ -1136,7 +1136,7 @@ if test "x$with_cups" != "xno" then ac_save_CPPFLAGS="$CPPFLAGS" ac_cups_cflags=`cups-config --cflags 2>/dev/null` - ac_cups_libs="`cups-config --ldflags 2>/dev/null` `cups-config --libs 2>/dev/null`" + ac_cups_libs=`cups-config --ldflags 2>/dev/null` CPPFLAGS="$CPPFLAGS $ac_cups_cflags" AC_CHECK_HEADERS(cups/cups.h, [WINE_CHECK_SONAME(cups,cupsGetDefault, @@ -1203,7 +1203,7 @@ dnl **** Check for libodbc **** WINE_CHECK_SONAME(odbc,SQLConnect,,[AC_DEFINE_UNQUOTED(SONAME_LIBODBC,["libodbc.$LIBEXT"])]) dnl **** Check for any sound system **** -if test "x$ALSALIBS$AUDIOIOLIBS$COREAUDIO$NASLIBS$ESD_LIBS$ac_cv_lib_soname_jack" = "x" -a \ +if test "x$ALSALIBS$AUDIOIOLIBS$COREAUDIO$NASLIBS$ESDLIBS$ac_cv_lib_soname_jack" = "x" -a \ "$ac_cv_header_sys_soundcard_h" != "yes" -a \ "$ac_cv_header_machine_soundcard_h" != "yes" -a \ "$ac_cv_header_soundcard_h" != "yes" -a \ @@ -1910,6 +1910,7 @@ AC_CONFIG_FILES([dlls/msi/Makefile]) AC_CONFIG_FILES([dlls/msi/tests/Makefile]) AC_CONFIG_FILES([dlls/msimg32/Makefile]) AC_CONFIG_FILES([dlls/msimtf/Makefile]) +AC_CONFIG_FILES([dlls/msisip/Makefile]) AC_CONFIG_FILES([dlls/msisys.ocx/Makefile]) AC_CONFIG_FILES([dlls/msnet32/Makefile]) AC_CONFIG_FILES([dlls/msrle32/Makefile]) diff --git a/dlls/Makefile.in b/dlls/Makefile.in index bbe28106899..62747311467 100644 --- a/dlls/Makefile.in +++ b/dlls/Makefile.in @@ -154,6 +154,7 @@ BASEDIRS = \ msi \ msimg32 \ msimtf \ + msisip \ msisys.ocx \ msnet32 \ msrle32 \ diff --git a/dlls/advapi32/cred.c b/dlls/advapi32/cred.c index 50a27c0b341..660091208e7 100644 --- a/dlls/advapi32/cred.c +++ b/dlls/advapi32/cred.c @@ -49,7 +49,6 @@ static const WCHAR wszEncryptionKeyValue[] = {'E','n','c','r','y','p','t','i','o static const WCHAR wszFlagsValue[] = {'F','l','a','g','s',0}; static const WCHAR wszTypeValue[] = {'T','y','p','e',0}; -static const WCHAR wszTargetNameValue[] = {'T','a','r','g','e','t','N','a','m','e',0}; static const WCHAR wszCommentValue[] = {'C','o','m','m','e','n','t',0}; static const WCHAR wszLastWrittenValue[] = {'L','a','s','t','W','r','i','t','t','e','n',0}; static const WCHAR wszPersistValue[] = {'P','e','r','s','i','s','t',0}; diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 94ce15af034..95608c6503a 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -159,9 +159,8 @@ static const char *wine_debugstr_wn( const WCHAR *str, int n ) #define ADVAPI32_GET_PROC(func) \ - p ## func = (void*)GetProcAddress(hadvapi32, #func); \ - if(!p ## func) \ - trace("GetProcAddress(%s) failed\n", #func); + p ## func = (void*)GetProcAddress(hadvapi32, #func); + static void InitFunctionPtrs(void) { @@ -332,13 +331,21 @@ static void test_set_value(void) test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A)); test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W)); - /* only REG_SZ is supported */ + /* only REG_SZ is supported on NT*/ ret = RegSetValueA(hkey_main, NULL, REG_BINARY, string2A, sizeof(string2A)); - ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret); + /* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_SUCCESS */ + ok(ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_SUCCESS), + "got %d (expected ERROR_INVALID_PARAMETER or ERROR_SUCCESS)\n", ret); + ret = RegSetValueA(hkey_main, NULL, REG_EXPAND_SZ, string2A, sizeof(string2A)); - ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret); + /* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_SUCCESS */ + ok(ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_SUCCESS), + "got %d (expected ERROR_INVALID_PARAMETER or ERROR_SUCCESS)\n", ret); + ret = RegSetValueA(hkey_main, NULL, REG_MULTI_SZ, string2A, sizeof(string2A)); - ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret); + /* NT: ERROR_INVALID_PARAMETER, 9x: ERROR_SUCCESS */ + ok(ret == ERROR_INVALID_PARAMETER || broken(ret == ERROR_SUCCESS), + "got %d (expected ERROR_INVALID_PARAMETER or ERROR_SUCCESS)\n", ret); /* Test RegSetValueExA with a 'zero-byte' string (as Office 2003 does). * Surprisingly enough we're supposed to get zero bytes out of it. diff --git a/dlls/appwiz.cpl/En.rc b/dlls/appwiz.cpl/En.rc index 155f46cc0e1..22c0879430b 100644 --- a/dlls/appwiz.cpl/En.rc +++ b/dlls/appwiz.cpl/En.rc @@ -28,6 +28,7 @@ STRINGTABLE IDS_TAB1_TITLE, "Applications" IDS_UNINSTALL_FAILED, "Unable to execute the uninstaller, '%s'. Do you want to remove the uninstall entry for this program from the registry?" + IDS_NOT_SPECIFIED, "Not specified" IDS_COLUMN_NAME, "Name" IDS_COLUMN_PUBLISHER, "Publisher" @@ -45,7 +46,7 @@ FONT 8, "MS Sans Serif" CONTROL "&Install...", IDC_INSTALL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 246, 26, 64, 14 CONTROL "", -1, "STATIC", SS_LEFT | SS_SUNKEN | WS_CHILD | WS_VISIBLE, 7, 46, 303, 1 CONTROL 2, 1001, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 7, 7, 21, 20 - CONTROL "The following software can be automatically removed. To remove a program or to modify its installed components, select it from the list and click Add/Remove.", 1002, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 40, 57, 270, 36 + CONTROL "The following software can be automatically removed. To remove a program or to modify its installed components, select it from the list and click Add/Remove.", 1002, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 40, 57, 270, 30 CONTROL "", IDL_PROGRAMS, "SysListView32", LVS_REPORT | LVS_SINGLESEL | LVS_SORTASCENDING | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 7, 90, 303, 100 CONTROL "Add/&Remove...", IDC_ADDREMOVE, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 246, 198, 64, 14 CONTROL "&Support Info...", IDC_SUPPORT_INFO, "button", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 176, 198, 64, 14 diff --git a/dlls/appwiz.cpl/appwiz.c b/dlls/appwiz.cpl/appwiz.c index e06d8100087..44bf3b24bdd 100644 --- a/dlls/appwiz.cpl/appwiz.c +++ b/dlls/appwiz.cpl/appwiz.c @@ -23,6 +23,8 @@ * */ +#define NONAMELESSUNION + #include "config.h" #include "wine/port.h" #include "wine/unicode.h" @@ -76,6 +78,14 @@ static const WCHAR DisplayIconW[] = {'D','i','s','p','l','a','y','I','c','o','n' static const WCHAR DisplayVersionW[] = {'D','i','s','p','l','a','y','V','e','r', 's','i','o','n',0}; static const WCHAR PublisherW[] = {'P','u','b','l','i','s','h','e','r',0}; +static const WCHAR ContactW[] = {'C','o','n','t','a','c','t',0}; +static const WCHAR HelpLinkW[] = {'H','e','l','p','L','i','n','k',0}; +static const WCHAR HelpTelephoneW[] = {'H','e','l','p','T','e','l','e','p','h', + 'o','n','e',0}; +static const WCHAR ReadmeW[] = {'R','e','a','d','m','e',0}; +static const WCHAR URLUpdateInfoW[] = {'U','R','L','U','p','d','a','t','e','I', + 'n','f','o',0}; +static const WCHAR CommentsW[] = {'C','o','m','m','e','n','t','s',0}; static const WCHAR UninstallCommandlineW[] = {'U','n','i','n','s','t','a','l','l', 'S','t','r','i','n','g',0}; @@ -416,6 +426,46 @@ static void UninstallProgram(int id) } } +/********************************************************************************** + * Name : SetInfoDialogText + * Description: Sets the text of a label in a window, based upon a registry entry + * or string passed to the function. + * Parameters : hKey - registry entry to read from, NULL if not reading + * from registry + * lpKeyName - key to read from, or string to check if hKey is NULL + * lpAltMessage - alternative message if entry not found + * hWnd - handle of dialog box + * iDlgItem - ID of label in dialog box + */ +static void SetInfoDialogText(HKEY hKey, LPWSTR lpKeyName, LPWSTR lpAltMessage, + HWND hWnd, int iDlgItem) +{ + WCHAR buf[MAX_STRING_LEN]; + DWORD buflen; + HWND hWndDlgItem; + + hWndDlgItem = GetDlgItem(hWnd, iDlgItem); + + /* if hKey is null, lpKeyName contains the string we want to check */ + if (hKey == NULL) + { + if ((lpKeyName) && (lstrlenW(lpKeyName) > 0)) + SetWindowTextW(hWndDlgItem, lpKeyName); + else + SetWindowTextW(hWndDlgItem, lpAltMessage); + } + else + { + buflen = MAX_STRING_LEN; + + if ((RegQueryValueExW(hKey, lpKeyName, 0, 0, (LPBYTE) buf, &buflen) == + ERROR_SUCCESS) && (lstrlenW(buf) > 0)) + SetWindowTextW(hWndDlgItem, buf); + else + SetWindowTextW(hWndDlgItem, lpAltMessage); + } +} + /****************************************************************************** * Name : SupportInfoDlgProc * Description: Callback procedure for support info dialog @@ -428,8 +478,11 @@ static void UninstallProgram(int id) static BOOL CALLBACK SupportInfoDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { APPINFO *iter; + HKEY hkey; WCHAR oldtitle[MAX_STRING_LEN]; WCHAR buf[MAX_STRING_LEN]; + WCHAR key[MAX_STRING_LEN]; + WCHAR notfound[MAX_STRING_LEN]; switch(msg) { @@ -438,6 +491,37 @@ static BOOL CALLBACK SupportInfoDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPAR { if (iter->id == (int) lParam) { + lstrcpyW(key, PathUninstallW); + lstrcatW(key, BackSlashW); + lstrcatW(key, iter->regkey); + + /* check the application's registry entries */ + RegOpenKeyExW(iter->regroot, key, 0, KEY_READ, &hkey); + + /* Load our "not specified" string */ + LoadStringW(hInst, IDS_NOT_SPECIFIED, notfound, + sizeof(notfound) / sizeof(notfound[0])); + + /* Update the data for items already read into the structure */ + SetInfoDialogText(NULL, iter->publisher, notfound, hWnd, + IDC_INFO_PUBLISHER); + SetInfoDialogText(NULL, iter->version, notfound, hWnd, + IDC_INFO_VERSION); + + /* And now update the data for those items in the registry */ + SetInfoDialogText(hkey, (LPWSTR) ContactW, notfound, hWnd, + IDC_INFO_CONTACT); + SetInfoDialogText(hkey, (LPWSTR) HelpLinkW, notfound, hWnd, + IDC_INFO_SUPPORT); + SetInfoDialogText(hkey, (LPWSTR) HelpTelephoneW, notfound, hWnd, + IDC_INFO_PHONE); + SetInfoDialogText(hkey, (LPWSTR) ReadmeW, notfound, hWnd, + IDC_INFO_README); + SetInfoDialogText(hkey, (LPWSTR) URLUpdateInfoW, notfound, hWnd, + IDC_INFO_UPDATES); + SetInfoDialogText(hkey, (LPWSTR) CommentsW, notfound, hWnd, + IDC_INFO_COMMENTS); + /* Update the main label with the app name */ if (GetWindowTextW(GetDlgItem(hWnd, IDC_INFO_LABEL), oldtitle, MAX_STRING_LEN) != 0) @@ -446,6 +530,8 @@ static BOOL CALLBACK SupportInfoDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPAR SetWindowTextW(GetDlgItem(hWnd, IDC_INFO_LABEL), buf); } + RegCloseKey(hkey); + break; } } @@ -505,7 +591,7 @@ static BOOL AddListViewColumns(HWND hWnd) { WCHAR buf[MAX_STRING_LEN]; LVCOLUMNW lvc; - int i; + UINT i; lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH; @@ -708,8 +794,8 @@ static void StartApplet(HWND hWnd) psp.dwSize = sizeof (PROPSHEETPAGEW); psp.dwFlags = PSP_USETITLE; psp.hInstance = hInst; - psp.pszTemplate = MAKEINTRESOURCEW (IDD_MAIN); - psp.pszIcon = NULL; + psp.u.pszTemplate = MAKEINTRESOURCEW (IDD_MAIN); + psp.u2.pszIcon = NULL; psp.pfnDlgProc = (DLGPROC) MainDlgProc; psp.pszTitle = tab_title; psp.lParam = 0; @@ -719,12 +805,12 @@ static void StartApplet(HWND hWnd) psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID; psh.hwndParent = hWnd; psh.hInstance = hInst; - psh.pszIcon = NULL; + psh.u.pszIcon = NULL; psh.pszCaption = app_title; psh.nPages = 1; - psh.ppsp = &psp; + psh.u3.ppsp = &psp; psh.pfnCallback = NULL; - psh.nStartPage = 0; + psh.u2.nStartPage = 0; /* Display the property sheet */ PropertySheetW (&psh); diff --git a/dlls/appwiz.cpl/appwiz.cpl.spec b/dlls/appwiz.cpl/appwiz.cpl.spec index 7ae3a0104c6..38960198273 100644 --- a/dlls/appwiz.cpl/appwiz.cpl.spec +++ b/dlls/appwiz.cpl/appwiz.cpl.spec @@ -1 +1 @@ -1 stdcall CPlApplet() +1 stdcall CPlApplet(long long long long) diff --git a/dlls/appwiz.cpl/res.h b/dlls/appwiz.cpl/res.h index ea32be8bd9e..34129c4d375 100644 --- a/dlls/appwiz.cpl/res.h +++ b/dlls/appwiz.cpl/res.h @@ -49,6 +49,7 @@ #define IDS_CPL_DESC 2 #define IDS_TAB1_TITLE 3 #define IDS_UNINSTALL_FAILED 4 +#define IDS_NOT_SPECIFIED 5 #define IDS_COLUMN_NAME 6 #define IDS_COLUMN_PUBLISHER 7 #define IDS_COLUMN_VERSION 8 diff --git a/dlls/browseui/progressdlg.c b/dlls/browseui/progressdlg.c index 3cd522ccf18..307ca2804a6 100644 --- a/dlls/browseui/progressdlg.c +++ b/dlls/browseui/progressdlg.c @@ -78,7 +78,7 @@ static void set_buffer(LPWSTR *buffer, LPCWSTR string) { static const WCHAR empty_string[] = {0}; IMalloc *malloc; - int cb; + ULONG cb; if (string == NULL) string = empty_string; diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c index a673b1b6da7..f909155420d 100644 --- a/dlls/comctl32/imagelist.c +++ b/dlls/comctl32/imagelist.c @@ -1899,7 +1899,7 @@ static int DIB_GetDIBImageBytes( int width, int height, int depth ) /* helper for ImageList_Read, see comments below */ -static BOOL _read_bitmap(HIMAGELIST himl, HDC hdcIml, LPSTREAM pstm) +static BOOL _read_bitmap(HDC hdcIml, LPSTREAM pstm) { BITMAPFILEHEADER bmfh; int bitsperpixel, palspace; @@ -2006,14 +2006,14 @@ HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm) if (!himl) return NULL; - if (!_read_bitmap(himl, himl->hdcImage, pstm)) + if (!_read_bitmap(himl->hdcImage, pstm)) { WARN("failed to read bitmap from stream\n"); return NULL; } if (ilHead.flags & ILC_MASK) { - if (!_read_bitmap(himl, himl->hdcMask, pstm)) + if (!_read_bitmap(himl->hdcMask, pstm)) { WARN("failed to read mask bitmap from stream\n"); return NULL; diff --git a/dlls/comctl32/tests/comboex.c b/dlls/comctl32/tests/comboex.c index 57143657e21..321b2a78b9f 100644 --- a/dlls/comctl32/tests/comboex.c +++ b/dlls/comctl32/tests/comboex.c @@ -183,6 +183,13 @@ static void test_WM_LBUTTONDOWN(void) WCHAR buffer[3]; static const UINT choices[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72}; static const WCHAR stringFormat[] = {'%','2','d','\0'}; + BOOL (WINAPI *pGetComboBoxInfo)(HWND, PCOMBOBOXINFO); + + pGetComboBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo"); + if (!pGetComboBoxInfo){ + skip("GetComboBoxInfo is not available\n"); + return; + } hComboEx = CreateWindowExA(0, WC_COMBOBOXEXA, NULL, WS_VISIBLE|WS_CHILD|CBS_DROPDOWN, 0, 0, 200, 150, @@ -205,7 +212,7 @@ static void test_WM_LBUTTONDOWN(void) hEdit = (HWND)SendMessage(hComboEx, CBEM_GETEDITCONTROL, 0, 0); cbInfo.cbSize = sizeof(COMBOBOXINFO); - result = GetComboBoxInfo(hCombo, &cbInfo); + result = pGetComboBoxInfo(hCombo, &cbInfo); ok(result, "Failed to get combobox info structure. LastError=%d\n", GetLastError()); hList = cbInfo.hwndList; diff --git a/dlls/comctl32/updown.c b/dlls/comctl32/updown.c index a971afa1c46..38879dbe40f 100644 --- a/dlls/comctl32/updown.c +++ b/dlls/comctl32/updown.c @@ -817,7 +817,6 @@ static void UPDOWN_HandleMouseEvent (UPDOWN_INFO *infoPtr, UINT msg, INT x, INT static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { UPDOWN_INFO *infoPtr = UPDOWN_GetInfoPtr (hwnd); - int temp; static const WCHAR themeClass[] = {'S','p','i','n',0}; HTHEME theme; @@ -903,6 +902,8 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L /* if initial timer, kill it and start the repeat timer */ if(wParam == TIMER_AUTOREPEAT) { + int temp; + KillTimer(hwnd, TIMER_AUTOREPEAT); /* if no accel info given, used default timer */ if(infoPtr->AccelCount==0 || infoPtr->AccelVect==0) { @@ -917,6 +918,8 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L /* now, if the mouse is above us, do the thing...*/ if(infoPtr->Flags & FLAG_MOUSEIN) { + int temp; + temp = infoPtr->AccelIndex == -1 ? 1 : infoPtr->AccelVect[infoPtr->AccelIndex].nInc; UPDOWN_DoAction(infoPtr, temp, infoPtr->Flags & FLAG_ARROW); @@ -972,13 +975,16 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L case UDM_GETACCEL: if (wParam==0 && lParam==0) return infoPtr->AccelCount; if (wParam && lParam) { - temp = min(infoPtr->AccelCount, wParam); + int temp = min(infoPtr->AccelCount, wParam); memcpy((void *)lParam, infoPtr->AccelVect, temp*sizeof(UDACCEL)); return temp; } return 0; case UDM_SETACCEL: + { + unsigned temp; + TRACE("UDM_SETACCEL\n"); if(infoPtr->AccelVect) { @@ -996,14 +1002,14 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L TRACE("%d: nSec %u nInc %u\n", temp, infoPtr->AccelVect[temp].nSec, infoPtr->AccelVect[temp].nInc); return TRUE; - + } case UDM_GETBASE: return infoPtr->Base; case UDM_SETBASE: TRACE("UpDown Ctrl new base(%ld), hwnd=%p\n", wParam, hwnd); if (wParam==10 || wParam==16) { - temp = infoPtr->Base; + WPARAM temp = infoPtr->Base; infoPtr->Base = wParam; return temp; } @@ -1016,11 +1022,14 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L return (LRESULT)UPDOWN_SetBuddy (infoPtr, (HWND)wParam); case UDM_GETPOS: - temp = UPDOWN_GetBuddyInt (infoPtr); + { + int temp = UPDOWN_GetBuddyInt (infoPtr); return MAKELONG(infoPtr->CurVal, temp ? 0 : 1); - + } case UDM_SETPOS: - temp = (short)LOWORD(lParam); + { + int temp = (short)LOWORD(lParam); + TRACE("UpDown Ctrl new value(%d), hwnd=%p\n", temp, hwnd); if(!UPDOWN_InBounds(infoPtr, temp)) { if(temp < infoPtr->MinVal) temp = infoPtr->MinVal; @@ -1030,7 +1039,7 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L infoPtr->CurVal = temp; UPDOWN_SetBuddyInt (infoPtr); return wParam; /* return prev value */ - + } case UDM_GETRANGE: return MAKELONG(infoPtr->MaxVal, infoPtr->MinVal); @@ -1062,6 +1071,9 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L return infoPtr->CurVal; case UDM_SETPOS32: + { + int temp; + if(!UPDOWN_InBounds(infoPtr, (int)lParam)) { if((int)lParam < infoPtr->MinVal) lParam = infoPtr->MinVal; if((int)lParam > infoPtr->MaxVal) lParam = infoPtr->MaxVal; @@ -1070,17 +1082,18 @@ static LRESULT WINAPI UpDownWindowProc(HWND hwnd, UINT message, WPARAM wParam, L infoPtr->CurVal = (int)lParam; /* set the new value */ UPDOWN_SetBuddyInt (infoPtr); return temp; /* return prev value */ - + } case UDM_GETUNICODEFORMAT: /* we lie a bit here, we're always using Unicode internally */ return infoPtr->UnicodeFormat; case UDM_SETUNICODEFORMAT: + { /* do we really need to honour this flag? */ - temp = infoPtr->UnicodeFormat; + int temp = infoPtr->UnicodeFormat; infoPtr->UnicodeFormat = (BOOL)wParam; return temp; - + } default: if ((message >= WM_USER) && (message < WM_APP) && !COMCTL32_IsReflectedMessage(message)) ERR("unknown msg %04x wp=%04lx lp=%08lx\n", message, wParam, lParam); diff --git a/dlls/comdlg32/fontdlg.c b/dlls/comdlg32/fontdlg.c index 2532f2ffc13..9174ce00d61 100644 --- a/dlls/comdlg32/fontdlg.c +++ b/dlls/comdlg32/fontdlg.c @@ -1072,7 +1072,7 @@ static LRESULT CFn_WMDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam, LPCHOOSEFO LF_FACESIZE, lpcfa->lpLogFont->lfFaceName, LF_FACESIZE, 0, 0); if((lpcfw->Flags & CF_USESTYLE) && lpcfw->lpszStyle) { - len = WideCharToMultiByte(CP_ACP, 0, lpcfw->lpszStyle, -1, NULL, -1, 0, 0); + len = WideCharToMultiByte(CP_ACP, 0, lpcfw->lpszStyle, -1, NULL, 0, 0, 0); WideCharToMultiByte(CP_ACP, 0, lpcfw->lpszStyle, -1, lpcfa->lpszStyle, len, 0, 0); HeapFree(GetProcessHeap(), 0, lpcfw->lpszStyle); } diff --git a/dlls/crypt32/Makefile.in b/dlls/crypt32/Makefile.in index 767a5b9805f..441efc4a05e 100644 --- a/dlls/crypt32/Makefile.in +++ b/dlls/crypt32/Makefile.in @@ -19,6 +19,7 @@ C_SRCS = \ encode.c \ filestore.c \ main.c \ + message.c \ msg.c \ object.c \ oid.c \ diff --git a/dlls/crypt32/crypt32.spec b/dlls/crypt32/crypt32.spec index b7f45d06b16..a5ef37dc2bf 100644 --- a/dlls/crypt32/crypt32.spec +++ b/dlls/crypt32/crypt32.spec @@ -129,7 +129,7 @@ @ stdcall CryptGetOIDFunctionAddress(long long str long ptr ptr) @ stdcall CryptGetOIDFunctionValue(long str str wstr ptr ptr ptr) @ stdcall CryptHashCertificate(long long long ptr long ptr ptr) -@ stub CryptHashMessage +@ stdcall CryptHashMessage(ptr long long ptr ptr ptr ptr ptr ptr) @ stdcall CryptHashPublicKeyInfo(long long long long ptr ptr ptr) @ stub CryptHashToBeSigned @ stub CryptImportPKCS8 diff --git a/dlls/crypt32/message.c b/dlls/crypt32/message.c new file mode 100644 index 00000000000..fe4d4ec1ce5 --- /dev/null +++ b/dlls/crypt32/message.c @@ -0,0 +1,270 @@ +/* + * Copyright 2007 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 "windef.h" +#include "winbase.h" +#include "wincrypt.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(crypt); + +HCERTSTORE WINAPI CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType, + HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const BYTE* pbSignedBlob, + DWORD cbSignedBlob) +{ + CRYPT_DATA_BLOB blob = { cbSignedBlob, (LPBYTE)pbSignedBlob }; + + TRACE("(%08x, %ld, %d08x %p, %d)\n", dwMsgAndCertEncodingType, hCryptProv, + dwFlags, pbSignedBlob, cbSignedBlob); + + return CertOpenStore(CERT_STORE_PROV_PKCS7, dwMsgAndCertEncodingType, + hCryptProv, dwFlags, &blob); +} + +LONG WINAPI CryptGetMessageSignerCount(DWORD dwMsgEncodingType, + const BYTE *pbSignedBlob, DWORD cbSignedBlob) +{ + HCRYPTMSG msg; + LONG count = -1; + + TRACE("(%08x, %p, %d)\n", dwMsgEncodingType, pbSignedBlob, cbSignedBlob); + + msg = CryptMsgOpenToDecode(dwMsgEncodingType, 0, 0, 0, NULL, NULL); + if (msg) + { + if (CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE)) + { + DWORD size = sizeof(count); + + CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 0, &count, &size); + } + CryptMsgClose(msg); + } + return count; +} + +static BOOL CRYPT_CopyParam(void *pvData, DWORD *pcbData, const void *src, + DWORD len) +{ + BOOL ret = TRUE; + + if (!pvData) + *pcbData = len; + else if (*pcbData < len) + { + *pcbData = len; + SetLastError(ERROR_MORE_DATA); + ret = FALSE; + } + else + { + *pcbData = len; + memcpy(pvData, src, len); + } + return ret; +} + +static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg, + DWORD dwSignerIndex) +{ + CERT_INFO *certInfo = NULL; + DWORD size; + + if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL, + &size)) + { + certInfo = CryptMemAlloc(size); + if (certInfo) + { + if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, + dwSignerIndex, certInfo, &size)) + { + CryptMemFree(certInfo); + certInfo = NULL; + } + } + } + return certInfo; +} + +static PCCERT_CONTEXT WINAPI CRYPT_DefaultGetSignerCertificate(void *pvGetArg, + DWORD dwCertEncodingType, PCERT_INFO pSignerId, HCERTSTORE hMsgCertStore) +{ + return CertFindCertificateInStore(hMsgCertStore, dwCertEncodingType, 0, + CERT_FIND_SUBJECT_CERT, pSignerId, NULL); +} + +static inline PCCERT_CONTEXT CRYPT_GetSignerCertificate(HCRYPTMSG msg, + PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, PCERT_INFO certInfo, HCERTSTORE store) +{ + PFN_CRYPT_GET_SIGNER_CERTIFICATE getCert; + + if (pVerifyPara->pfnGetSignerCertificate) + getCert = pVerifyPara->pfnGetSignerCertificate; + else + getCert = CRYPT_DefaultGetSignerCertificate; + return getCert(pVerifyPara->pvGetArg, + pVerifyPara->dwMsgAndCertEncodingType, certInfo, store); +} + +BOOL WINAPI CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, + DWORD dwSignerIndex, const BYTE* pbSignedBlob, DWORD cbSignedBlob, + BYTE* pbDecoded, DWORD* pcbDecoded, PCCERT_CONTEXT* ppSignerCert) +{ + BOOL ret = FALSE; + DWORD size; + CRYPT_CONTENT_INFO *contentInfo; + + TRACE("(%p, %d, %p, %d, %p, %p, %p)\n", + pVerifyPara, dwSignerIndex, pbSignedBlob, cbSignedBlob, + pbDecoded, pcbDecoded, ppSignerCert); + + if (ppSignerCert) + *ppSignerCert = NULL; + if (pcbDecoded) + *pcbDecoded = 0; + if (!pVerifyPara || + pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) || + GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) != + PKCS_7_ASN_ENCODING) + { + SetLastError(E_INVALIDARG); + return FALSE; + } + + ret = CryptDecodeObjectEx(pVerifyPara->dwMsgAndCertEncodingType, + PKCS_CONTENT_INFO, pbSignedBlob, cbSignedBlob, + CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, + (LPBYTE)&contentInfo, &size); + if (ret) + { + if (strcmp(contentInfo->pszObjId, szOID_RSA_signedData)) + { + SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE); + ret = FALSE; + } + else + { + HCRYPTMSG msg = CryptMsgOpenToDecode( + pVerifyPara->dwMsgAndCertEncodingType, 0, CMSG_SIGNED, + pVerifyPara->hCryptProv, NULL, NULL); + + if (msg) + { + ret = CryptMsgUpdate(msg, contentInfo->Content.pbData, + contentInfo->Content.cbData, TRUE); + if (ret && pcbDecoded) + ret = CRYPT_CopyParam(pbDecoded, pcbDecoded, + contentInfo->Content.pbData, contentInfo->Content.cbData); + if (ret) + { + CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg, + dwSignerIndex); + + ret = FALSE; + if (certInfo) + { + HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG, + pVerifyPara->dwMsgAndCertEncodingType, + pVerifyPara->hCryptProv, 0, msg); + + if (store) + { + PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate( + msg, pVerifyPara, certInfo, store); + + if (cert) + { + ret = CryptMsgControl(msg, 0, + CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo); + if (ret && ppSignerCert) + *ppSignerCert = cert; + else + CertFreeCertificateContext(cert); + } + CertCloseStore(store, 0); + } + } + CryptMemFree(certInfo); + } + CryptMsgClose(msg); + } + } + LocalFree(contentInfo); + } + TRACE("returning %d\n", ret); + return ret; +} + +BOOL WINAPI CryptHashMessage(PCRYPT_HASH_MESSAGE_PARA pHashPara, + BOOL fDetachedHash, DWORD cToBeHashed, const BYTE *rgpbToBeHashed[], + DWORD rgcbToBeHashed[], BYTE *pbHashedBlob, DWORD *pcbHashedBlob, + BYTE *pbComputedHash, DWORD *pcbComputedHash) +{ + DWORD i, flags; + BOOL ret = FALSE; + HCRYPTMSG msg; + CMSG_HASHED_ENCODE_INFO info; + + TRACE("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n", pHashPara, fDetachedHash, + cToBeHashed, rgpbToBeHashed, rgcbToBeHashed, pbHashedBlob, pcbHashedBlob, + pbComputedHash, pcbComputedHash); + + if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA)) + { + SetLastError(E_INVALIDARG); + return FALSE; + } + /* Native seems to ignore any encoding type other than the expected + * PKCS_7_ASN_ENCODING + */ + if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) != + PKCS_7_ASN_ENCODING) + return TRUE; + /* Native also seems to do nothing if the output parameter isn't given */ + if (!pcbHashedBlob) + return TRUE; + + flags = fDetachedHash ? CMSG_DETACHED_FLAG : 0; + memset(&info, 0, sizeof(info)); + info.cbSize = sizeof(info); + info.hCryptProv = pHashPara->hCryptProv; + memcpy(&info.HashAlgorithm, &pHashPara->HashAlgorithm, + sizeof(info.HashAlgorithm)); + info.pvHashAuxInfo = pHashPara->pvHashAuxInfo; + msg = CryptMsgOpenToEncode(pHashPara->dwMsgEncodingType, flags, CMSG_HASHED, + &info, NULL, NULL); + if (msg) + { + for (i = 0, ret = TRUE; ret && i < cToBeHashed; i++) + ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i], + i == cToBeHashed - 1 ? TRUE : FALSE); + if (ret) + { + ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbHashedBlob, + pcbHashedBlob); + if (ret && pcbComputedHash) + ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, + pbComputedHash, pcbComputedHash); + } + CryptMsgClose(msg); + } + return ret; +} diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c index 1bb8767b4c6..4571607e935 100644 --- a/dlls/crypt32/msg.c +++ b/dlls/crypt32/msg.c @@ -2445,170 +2445,3 @@ BOOL WINAPI CryptMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags, pvCtrlPara); return msg->control(hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara); } - -HCERTSTORE WINAPI CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType, - HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const BYTE* pbSignedBlob, - DWORD cbSignedBlob) -{ - CRYPT_DATA_BLOB blob = { cbSignedBlob, (LPBYTE)pbSignedBlob }; - - TRACE("(%08x, %ld, %d08x %p, %d)\n", dwMsgAndCertEncodingType, hCryptProv, - dwFlags, pbSignedBlob, cbSignedBlob); - - return CertOpenStore(CERT_STORE_PROV_PKCS7, dwMsgAndCertEncodingType, - hCryptProv, dwFlags, &blob); -} - -LONG WINAPI CryptGetMessageSignerCount(DWORD dwMsgEncodingType, - const BYTE *pbSignedBlob, DWORD cbSignedBlob) -{ - HCRYPTMSG msg; - LONG count = -1; - - TRACE("(%08x, %p, %d)\n", dwMsgEncodingType, pbSignedBlob, cbSignedBlob); - - msg = CryptMsgOpenToDecode(dwMsgEncodingType, 0, 0, 0, NULL, NULL); - if (msg) - { - if (CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE)) - { - DWORD size = sizeof(count); - - CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 0, &count, &size); - } - CryptMsgClose(msg); - } - return count; -} - -static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg, - DWORD dwSignerIndex) -{ - CERT_INFO *certInfo = NULL; - DWORD size; - - if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL, - &size)) - { - certInfo = CryptMemAlloc(size); - if (certInfo) - { - if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, - dwSignerIndex, certInfo, &size)) - { - CryptMemFree(certInfo); - certInfo = NULL; - } - } - } - return certInfo; -} - -static PCCERT_CONTEXT WINAPI CRYPT_DefaultGetSignerCertificate(void *pvGetArg, - DWORD dwCertEncodingType, PCERT_INFO pSignerId, HCERTSTORE hMsgCertStore) -{ - return CertFindCertificateInStore(hMsgCertStore, dwCertEncodingType, 0, - CERT_FIND_SUBJECT_CERT, pSignerId, NULL); -} - -static inline PCCERT_CONTEXT CRYPT_GetSignerCertificate(HCRYPTMSG msg, - PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, PCERT_INFO certInfo, HCERTSTORE store) -{ - PFN_CRYPT_GET_SIGNER_CERTIFICATE getCert; - - if (pVerifyPara->pfnGetSignerCertificate) - getCert = pVerifyPara->pfnGetSignerCertificate; - else - getCert = CRYPT_DefaultGetSignerCertificate; - return getCert(pVerifyPara->pvGetArg, - pVerifyPara->dwMsgAndCertEncodingType, certInfo, store); -} - -BOOL WINAPI CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, - DWORD dwSignerIndex, const BYTE* pbSignedBlob, DWORD cbSignedBlob, - BYTE* pbDecoded, DWORD* pcbDecoded, PCCERT_CONTEXT* ppSignerCert) -{ - BOOL ret = FALSE; - DWORD size; - CRYPT_CONTENT_INFO *contentInfo; - - TRACE("(%p, %d, %p, %d, %p, %p, %p)\n", - pVerifyPara, dwSignerIndex, pbSignedBlob, cbSignedBlob, - pbDecoded, pcbDecoded, ppSignerCert); - - if (ppSignerCert) - *ppSignerCert = NULL; - if (pcbDecoded) - *pcbDecoded = 0; - if (!pVerifyPara || - pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) || - GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) != - PKCS_7_ASN_ENCODING) - { - SetLastError(E_INVALIDARG); - return FALSE; - } - - ret = CryptDecodeObjectEx(pVerifyPara->dwMsgAndCertEncodingType, - PKCS_CONTENT_INFO, pbSignedBlob, cbSignedBlob, - CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, NULL, - (LPBYTE)&contentInfo, &size); - if (ret) - { - if (strcmp(contentInfo->pszObjId, szOID_RSA_signedData)) - { - SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE); - ret = FALSE; - } - else - { - HCRYPTMSG msg = CryptMsgOpenToDecode( - pVerifyPara->dwMsgAndCertEncodingType, 0, CMSG_SIGNED, - pVerifyPara->hCryptProv, NULL, NULL); - - if (msg) - { - ret = CryptMsgUpdate(msg, contentInfo->Content.pbData, - contentInfo->Content.cbData, TRUE); - if (ret && pcbDecoded) - ret = CRYPT_CopyParam(pbDecoded, pcbDecoded, - contentInfo->Content.pbData, contentInfo->Content.cbData); - if (ret) - { - CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg, - dwSignerIndex); - - ret = FALSE; - if (certInfo) - { - HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG, - pVerifyPara->dwMsgAndCertEncodingType, - pVerifyPara->hCryptProv, 0, msg); - - if (store) - { - PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate( - msg, pVerifyPara, certInfo, store); - - if (cert) - { - ret = CryptMsgControl(msg, 0, - CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo); - if (ret && ppSignerCert) - *ppSignerCert = cert; - else - CertFreeCertificateContext(cert); - } - CertCloseStore(store, 0); - } - } - CryptMemFree(certInfo); - } - CryptMsgClose(msg); - } - } - LocalFree(contentInfo); - } - TRACE("returning %d\n", ret); - return ret; -} diff --git a/dlls/crypt32/sip.c b/dlls/crypt32/sip.c index f8e8be45612..171165a6c6d 100644 --- a/dlls/crypt32/sip.c +++ b/dlls/crypt32/sip.c @@ -332,7 +332,7 @@ BOOL WINAPI CryptSIPRetrieveSubjectGuid bRet = TRUE; goto cleanup1; } - /* Quick-n-dirty check for a cab file. FIXME: use FDIIsCabinet instead? */ + /* Quick-n-dirty check for a cab file. */ if (!memcmp(pMapped, cabHdr, sizeof(cabHdr))) { *pgSubject = cabGUID; diff --git a/dlls/crypt32/tests/Makefile.in b/dlls/crypt32/tests/Makefile.in index 89d6df586d3..07f0daec822 100644 --- a/dlls/crypt32/tests/Makefile.in +++ b/dlls/crypt32/tests/Makefile.in @@ -12,6 +12,7 @@ CTESTS = \ crl.c \ encode.c \ main.c \ + message.c \ msg.c \ oid.c \ protectdata.c \ diff --git a/dlls/crypt32/tests/cert.c b/dlls/crypt32/tests/cert.c index 37cea106b3a..2217da74f10 100644 --- a/dlls/crypt32/tests/cert.c +++ b/dlls/crypt32/tests/cert.c @@ -37,8 +37,8 @@ static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT static BOOL (WINAPI * pCryptVerifyCertificateSignatureEx) (HCRYPTPROV, DWORD, DWORD, void *, DWORD, void *, DWORD, void *); -static BOOL (WINAPI * pCryptAcquireContextW) - (HCRYPTPROV *, LPCWSTR, LPCWSTR, DWORD, DWORD); +static BOOL (WINAPI * pCryptAcquireContextA) + (HCRYPTPROV *, LPCSTR, LPCSTR, DWORD, DWORD); static void init_function_pointers(void) { @@ -57,7 +57,7 @@ static void init_function_pointers(void) GET_PROC(hCrypt32, CryptEncodeObjectEx) GET_PROC(hCrypt32, CryptVerifyCertificateSignatureEx) - GET_PROC(hAdvapi32, CryptAcquireContextW) + GET_PROC(hAdvapi32, CryptAcquireContextA) #undef GET_PROC } @@ -157,19 +157,23 @@ static void testAddCert(void) return; /* Weird--bad add disposition leads to an access violation in Windows. + * Both tests crash on some win9x boxes. */ - ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert, - sizeof(bigCert), 0, NULL); - ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION || - GetLastError() == E_INVALIDARG), - "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n", - GetLastError()); - ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, - bigCert, sizeof(bigCert), 0, NULL); - ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION || - GetLastError() == E_INVALIDARG), - "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n", - GetLastError()); + if (0) + { + ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert, + sizeof(bigCert), 0, NULL); + ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION || + GetLastError() == E_INVALIDARG), + "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n", + GetLastError()); + ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, + bigCert, sizeof(bigCert), 0, NULL); + ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION || + GetLastError() == E_INVALIDARG), + "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n", + GetLastError()); + } /* Weird--can add a cert to the NULL store (does this have special * meaning?) @@ -342,6 +346,7 @@ static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID, dwSizeWithNull,size); } +static CHAR cspNameA[] = "WineCryptTemp"; static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 }; static const BYTE v1CertWithPubKey[] = { 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30, @@ -1689,9 +1694,9 @@ static void testCertSigs(void) DWORD sigSize = sizeof(sig); /* Just in case a previous run failed, delete this thing */ - pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL, + pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_DELETEKEYSET); - ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL, + ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_NEWKEYSET); ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError()); @@ -1700,7 +1705,7 @@ static void testCertSigs(void) CryptDestroyKey(key); CryptReleaseContext(csp, 0); - ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL, + ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_DELETEKEYSET); } @@ -1746,10 +1751,14 @@ static void testSignAndEncodeCert(void) &algID, NULL, NULL, &size); ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); - ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, - X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size); - ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, - "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); + /* Crashes on some win9x boxes */ + if (0) + { + ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, + X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size); + ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, + "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); + } /* Crashes ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size); @@ -1822,9 +1831,9 @@ static void testCreateSelfSignCert(void) */ /* Acquire a CSP */ - pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL, + pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_DELETEKEYSET); - ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL, + ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_NEWKEYSET); ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError()); @@ -1879,7 +1888,7 @@ static void testCreateSelfSignCert(void) } CryptReleaseContext(csp, 0); - ret = pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL, + ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_DELETEKEYSET); /* do the same test with AT_KEYEXCHANGE and key info*/ @@ -1927,7 +1936,7 @@ static void testCreateSelfSignCert(void) CertFreeCertificateContext(context); } - pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL, + pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_DELETEKEYSET); } @@ -2522,9 +2531,13 @@ static void testHashPublicKeyInfo(void) ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len); ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); - ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len); - ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, - "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); + /* Crashes on some win9x boxes */ + if (0) + { + ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len); + ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, + "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); + } ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len); ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError()); ok(len == 16, "Expected hash size 16, got %d\n", len); @@ -2755,7 +2768,7 @@ static void testAcquireCertPrivateKey(void) keyProvInfo.rgProvParam = NULL; keyProvInfo.dwKeySpec = AT_SIGNATURE; - pCryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL, + pCryptAcquireContextA(NULL, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_DELETEKEYSET); cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert, @@ -2788,7 +2801,7 @@ static void testAcquireCertPrivateKey(void) ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY, "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError()); - pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL, + pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_NEWKEYSET); ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key); ok(ret, "CryptImportKey failed: %08x\n", GetLastError()); @@ -2910,7 +2923,7 @@ static void testAcquireCertPrivateKey(void) } CryptReleaseContext(csp, 0); - pCryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL, + pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL, CRYPT_DELETEKEYSET); CertFreeCertificateContext(cert); diff --git a/dlls/crypt32/tests/chain.c b/dlls/crypt32/tests/chain.c index 91cae474429..5bae989367a 100644 --- a/dlls/crypt32/tests/chain.c +++ b/dlls/crypt32/tests/chain.c @@ -1741,6 +1741,14 @@ static ChainPolicyCheck basicConstraintsPolicyCheck[] = { { 0, 0, -1, -1, NULL }, 0 }, }; +static const char *num_to_str(WORD num) +{ + static char buf[6]; + + sprintf(buf, "#%04X", num); + return buf; +} + static void checkChainPolicyStatus(LPCSTR policy, ChainPolicyCheck *check, DWORD testIndex) { @@ -1757,8 +1765,17 @@ static void checkChainPolicyStatus(LPCSTR policy, ChainPolicyCheck *check, todo_wine ok(ret, "%d: CertVerifyCertificateChainPolicy failed: %08x\n", testIndex, GetLastError()); else + { + if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) + { + skip("%d: missing policy %s, skipping test\n", testIndex, + HIWORD(policy) ? policy : num_to_str(LOWORD(policy))); + pCertFreeCertificateChain(chain); + return; + } ok(ret, "%d: CertVerifyCertificateChainPolicy failed: %08x\n", testIndex, GetLastError()); + } if (ret) { if (check->todo & TODO_ERROR) diff --git a/dlls/crypt32/tests/message.c b/dlls/crypt32/tests/message.c new file mode 100644 index 00000000000..11b8c1c1fce --- /dev/null +++ b/dlls/crypt32/tests/message.c @@ -0,0 +1,409 @@ +/* + * Unit test suite for crypt32.dll's Crypt*Message functions + * + * Copyright 2007-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 + +#include "wine/test.h" + +static const BYTE dataEmptyBareContent[] = { 0x04,0x00 }; +static const BYTE dataEmptyContent[] = { +0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02, +0x04,0x00 }; +static const BYTE signedEmptyBareContent[] = { +0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86, +0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02, +0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03, +0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01, +0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30, +0x04,0x06,0x00,0x05,0x00,0x04,0x00 }; +static const BYTE signedEmptyContent[] = { +0x30,0x5f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x52, +0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86, +0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02, +0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03, +0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01, +0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30, +0x04,0x06,0x00,0x05,0x00,0x04,0x00 }; + +static void test_msg_get_signer_count(void) +{ + LONG count; + + SetLastError(0xdeadbeef); + count = CryptGetMessageSignerCount(0, NULL, 0); + ok(count == -1, "Expected -1, got %d\n", count); + ok(GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", + GetLastError()); + SetLastError(0xdeadbeef); + count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, NULL, 0); + ok(count == -1, "Expected -1, got %d\n", count); + ok(GetLastError() == CRYPT_E_ASN1_EOD, + "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, + dataEmptyBareContent, sizeof(dataEmptyBareContent)); + ok(count == -1, "Expected -1, got %d\n", count); + ok(GetLastError() == CRYPT_E_ASN1_BADTAG, + "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, + dataEmptyContent, sizeof(dataEmptyContent)); + ok(count == -1, "Expected -1, got %d\n", count); + ok(GetLastError() == CRYPT_E_INVALID_MSG_TYPE, + "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, + signedEmptyBareContent, sizeof(signedEmptyBareContent)); + ok(count == -1, "Expected -1, got %d\n", count); + ok(GetLastError() == CRYPT_E_ASN1_BADTAG, + "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); + count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, + signedEmptyContent, sizeof(signedEmptyContent)); + ok(count == 1, "Expected 1, got %d\n", count); +} + +static const BYTE signedContent[] = { +0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0, +0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a, +0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86, +0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04, +0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11, +0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, +0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, +0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70, +0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d, +0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe, +0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29, +0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8, +0x0d }; +static const BYTE signedWithCertEmptyContent[] = { +0x30,0x81,0xdf,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0, +0x81,0xd1,0x30,0x81,0xce,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a, +0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c, +0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11, +0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, +0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30, +0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30, +0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06, +0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67, +0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30, +0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01, +0xff,0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15, +0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e, +0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86, +0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04, +0x00 }; +static const BYTE signedWithCertContent[] = { +0x30,0x82,0x01,0x32,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02, +0xa0,0x82,0x01,0x23,0x30,0x82,0x01,0x1f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c, +0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06, +0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01, +0x02,0x03,0x04,0xa0,0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30, +0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61, +0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31, +0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36, +0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15, +0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e, +0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00, +0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04, +0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01, +0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13, +0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30, +0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04, +0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1, +0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9, +0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11, +0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19, +0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d }; +static const BYTE signedWithCertWithPubKeyContent[] = { +0x30,0x81,0xfc,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0, +0x81,0xee,0x30,0x81,0xeb,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a, +0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x81, +0x98,0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13, +0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c, +0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30, +0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30, +0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30, +0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61, +0x6e,0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d, +0x01,0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06, +0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12, +0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff, +0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31, +0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20, +0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48, +0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 }; + +static void test_verify_message_signature(void) +{ + BOOL ret; + CRYPT_VERIFY_MESSAGE_PARA para = { 0 }; + PCCERT_CONTEXT cert; + DWORD cbDecoded; + + SetLastError(0xdeadbeef); + ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, 0, NULL); + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL); + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %08x\n", GetLastError()); + para.cbSize = sizeof(para); + SetLastError(0xdeadbeef); + ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL); + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %08x\n", GetLastError()); + para.cbSize = 0; + para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING; + SetLastError(0xdeadbeef); + ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL); + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %08x\n", GetLastError()); + para.cbSize = sizeof(para); + SetLastError(0xdeadbeef); + ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL); + ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD, + "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError()); + /* Check whether cert is set on error */ + cert = (PCCERT_CONTEXT)0xdeadbeef; + ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, &cert); + ok(cert == NULL, "Expected NULL cert\n"); + /* Check whether cbDecoded is set on error */ + cbDecoded = 0xdeadbeef; + ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, &cbDecoded, + NULL); + ok(!cbDecoded, "Expected 0\n"); + SetLastError(0xdeadbeef); + ret = CryptVerifyMessageSignature(¶, 0, dataEmptyBareContent, + sizeof(dataEmptyBareContent), NULL, 0, NULL); + ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG, + "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = CryptVerifyMessageSignature(¶, 0, dataEmptyContent, + sizeof(dataEmptyContent), NULL, 0, NULL); + ok(!ret && GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE, + "Expected CRYPT_E_UNEXPECTED_MSG_TYPE, got %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = CryptVerifyMessageSignature(¶, 0, signedEmptyBareContent, + sizeof(signedEmptyBareContent), NULL, 0, NULL); + ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG, + "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = CryptVerifyMessageSignature(¶, 0, signedEmptyContent, + sizeof(signedEmptyContent), NULL, 0, NULL); + ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, + "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = CryptVerifyMessageSignature(¶, 0, signedContent, + sizeof(signedContent), NULL, 0, NULL); + ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, + "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); + /* FIXME: Windows fails with CRYPT_E_NOT_FOUND for these messages, but + * their signer certs have invalid public keys that fail to decode. In + * Wine therefore the failure is an ASN error. Need some messages with + * valid public keys and invalid signatures to check against. + */ + ret = CryptVerifyMessageSignature(¶, 0, signedWithCertEmptyContent, + sizeof(signedWithCertEmptyContent), NULL, 0, NULL); + ok(!ret, "Expected failure\n"); + ret = CryptVerifyMessageSignature(¶, 0, signedWithCertContent, + sizeof(signedWithCertContent), NULL, 0, NULL); + ok(!ret, "Expected failure\n"); + ret = CryptVerifyMessageSignature(¶, 0, signedWithCertWithPubKeyContent, + sizeof(signedWithCertWithPubKeyContent), NULL, 0, NULL); + ok(!ret, "Expected failure\n"); +} + +static const BYTE detachedHashBlob[] = { +0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32, +0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, +0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, +0x07,0x01,0x04,0x10,0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6, +0x24,0xb9,0x66,0x7c,0x21 }; +static const BYTE hashBlob[] = { +0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a, +0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d, +0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, +0x07,0x01,0xa0,0x06,0x04,0x04,0xde,0xad,0xbe,0xef,0x04,0x10,0x2f,0x24,0x92, +0x30,0xa8,0xe7,0xc2,0xbf,0x60,0x05,0xcc,0xd2,0x67,0x92,0x59,0xec }; +static const BYTE hashVal[] = { +0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,0x24,0xb9,0x66,0x7c, +0x21 }; + +static void test_hash_message(void) +{ + BOOL ret; + CRYPT_HASH_MESSAGE_PARA para; + static const BYTE blob1[] = { 0xde, 0xad, 0xbe, 0xef }; + static const BYTE blob2[] = { 0xba, 0xad, 0xf0, 0x0d }; + const BYTE *toHash[] = { blob1, blob2 }; + DWORD hashSize[] = { sizeof(blob1), sizeof(blob2) }; + DWORD hashedBlobSize, computedHashSize; + static char oid_rsa_md5[] = szOID_RSA_MD5; + LPBYTE hashedBlob, computedHash; + + /* Crash + ret = CryptHashMessage(NULL, FALSE, 0, NULL, 0, NULL, NULL, NULL, NULL); + */ + memset(¶, 0, sizeof(para)); + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL); + ok(!ret && GetLastError() == E_INVALIDARG, + "expected E_INVALIDARG, got 0x%08x\n", GetLastError()); + para.cbSize = sizeof(para); + /* Not quite sure what "success" means in this case, but it does succeed */ + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL); + ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); + /* With a bogus encoding type it "succeeds" */ + para.dwMsgEncodingType = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL); + ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); + /* According to MSDN, the third parameter (cToBeHashed) must be 1 if the + * second parameter (fDetached) is FALSE, but again it "succeeds." + */ + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL); + ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); + /* Even passing parameters to hash results in "success." */ + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL, NULL, NULL, + NULL); + /* Try again with a valid encoding type */ + para.dwMsgEncodingType = PKCS_7_ASN_ENCODING; + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL); + ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); + /* And with valid data to hash */ + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL, NULL, NULL, + NULL); + ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); + /* But requesting the size of the hashed blob and indicating there's data + * to hash results in a crash + */ + if (0) + { + ret = CryptHashMessage(¶, FALSE, 2, NULL, NULL, NULL, + &hashedBlobSize, NULL, NULL); + } + /* Passing a valid pointer for the data to hash fails, as the hash + * algorithm is finally checked. + */ + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL, + &hashedBlobSize, NULL, NULL); + ok(!ret && GetLastError() == CRYPT_E_UNKNOWN_ALGO, + "expected CRYPT_E_UNKNOWN_ALGO, got 0x%08x (%d)\n", GetLastError(), + GetLastError()); + para.HashAlgorithm.pszObjId = oid_rsa_md5; + /* With a valid hash algorithm, this succeeds, even though fDetached is + * FALSE. + */ + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL, + &hashedBlobSize, NULL, NULL); + todo_wine + ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); + if (ret) + { + /* Actually attempting to get the hashed data fails, perhaps because + * detached is FALSE. + */ + hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize); + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, hashedBlob, + &hashedBlobSize, NULL, NULL); + ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR, + "expected CRYPT_E_MSG_ERROR, got 0x%08x (%d)\n", GetLastError(), + GetLastError()); + HeapFree(GetProcessHeap(), 0, hashedBlob); + } + /* Repeating tests with fDetached = TRUE results in success */ + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, NULL, + &hashedBlobSize, NULL, NULL); + ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); + if (ret) + { + hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize); + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, hashedBlob, + &hashedBlobSize, NULL, NULL); + ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); + ok(hashedBlobSize == sizeof(detachedHashBlob), + "unexpected size of detached blob %d\n", hashedBlobSize); + ok(!memcmp(hashedBlob, detachedHashBlob, hashedBlobSize), + "unexpected detached blob value\n"); + HeapFree(GetProcessHeap(), 0, hashedBlob); + } + /* Hashing a single item with fDetached = FALSE also succeeds */ + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, FALSE, 1, toHash, hashSize, NULL, + &hashedBlobSize, NULL, NULL); + ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); + if (ret) + { + hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize); + ret = CryptHashMessage(¶, FALSE, 1, toHash, hashSize, hashedBlob, + &hashedBlobSize, NULL, NULL); + ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); + ok(hashedBlobSize == sizeof(hashBlob), + "unexpected size of detached blob %d\n", hashedBlobSize); + ok(!memcmp(hashedBlob, hashBlob, hashedBlobSize), + "unexpected detached blob value\n"); + HeapFree(GetProcessHeap(), 0, hashedBlob); + } + /* Check the computed hash value too. You don't need to get the encoded + * blob to get it. + */ + computedHashSize = 0xdeadbeef; + ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, NULL, + &hashedBlobSize, NULL, &computedHashSize); + ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError()); + ok(computedHashSize == 16, "expected hash size of 16, got %d\n", + computedHashSize); + if (ret) + { + computedHash = HeapAlloc(GetProcessHeap(), 0, computedHashSize); + SetLastError(0xdeadbeef); + ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, NULL, + &hashedBlobSize, computedHash, &computedHashSize); + ok(computedHashSize == sizeof(hashVal), + "unexpected size of hash value %d\n", computedHashSize); + ok(!memcmp(computedHash, hashVal, computedHashSize), + "unexpected value\n"); + HeapFree(GetProcessHeap(), 0, computedHash); + } +} + +START_TEST(message) +{ + test_msg_get_signer_count(); + test_verify_message_signature(); + test_hash_message(); +} diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c index 592b59e2a96..bfebeaada81 100644 --- a/dlls/crypt32/tests/msg.c +++ b/dlls/crypt32/tests/msg.c @@ -383,9 +383,10 @@ static void test_data_msg_update(void) /* Can't update a message with no data */ SetLastError(0xdeadbeef); ret = CryptMsgUpdate(msg, NULL, 0, TRUE); - /* NT: E_INVALIDARG, 9x: unchanged */ - ok(!ret && (GetLastError() == E_INVALIDARG || GetLastError() == 0xdeadbeef), - "Expected E_INVALIDARG or 0xdeadbeef, got 0x%x\n", GetLastError()); + /* This test returns FALSE on XP and earlier but TRUE on Vista, so can't be tested. + * GetLastError is either E_INVALIDARG (NT) or unset (9x/Vista), so it doesn't + * make sense to test this. + */ /* Curiously, a valid update will now fail as well, presumably because of * the last (invalid, but final) update. @@ -809,10 +810,11 @@ static void test_hash_msg_get_param(void) /* By getting the hash, further updates are not allowed */ SetLastError(0xdeadbeef); ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); - /* NT: NTE_BAD_HASH_STATE, 9x: NTE_BAD_ALGID */ ok(!ret && - (GetLastError() == NTE_BAD_HASH_STATE || GetLastError() == NTE_BAD_ALGID), - "Expected NTE_BAD_HASH_STATE or NTE_BAD_ALGID, got 0x%x\n", GetLastError()); + (GetLastError() == NTE_BAD_HASH_STATE /* NT */ || + GetLastError() == NTE_BAD_ALGID /* 9x */ || + GetLastError() == CRYPT_E_MSG_ERROR /* Vista */), + "Expected NTE_BAD_HASH_STATE or NTE_BAD_ALGID or CRYPT_E_MSG_ERROR, got 0x%x\n", GetLastError()); /* Even after a final update, the hash data aren't available */ SetLastError(0xdeadbeef); @@ -857,10 +859,11 @@ static void test_hash_msg_get_param(void) */ SetLastError(0xdeadbeef); ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); - /* NT: NTE_BAD_HASH_STATE, 9x: NTE_BAD_ALGID */ ok(!ret && - (GetLastError() == NTE_BAD_HASH_STATE || GetLastError() == NTE_BAD_ALGID), - "Expected NTE_BAD_HASH_STATE or NTE_BAD_ALGID, got 0x%x\n", GetLastError()); + (GetLastError() == NTE_BAD_HASH_STATE /* NT */ || + GetLastError() == NTE_BAD_ALGID /* 9x */ || + GetLastError() == CRYPT_E_MSG_ERROR /* Vista */), + "Expected NTE_BAD_HASH_STATE or NTE_BAD_ALGID or CRYPT_E_MSG_ERROR, got 0x%x\n", GetLastError()); CryptMsgClose(msg); } @@ -2462,24 +2465,30 @@ static void test_msg_control(void) /* Again, cert info needs to have a public key set */ SetLastError(0xdeadbeef); ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo); - ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD, - "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError()); + ok(!ret && + (GetLastError() == CRYPT_E_ASN1_EOD || + GetLastError() == TRUST_E_NOSIGNATURE /* Vista */), + "Expected CRYPT_E_ASN1_EOD or TRUST_E_NOSIGNATURE, got %08x\n", GetLastError()); /* The public key is supposed to be in encoded form.. */ certInfo.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa; certInfo.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey); certInfo.SubjectPublicKeyInfo.PublicKey.pbData = aKey; SetLastError(0xdeadbeef); ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo); - ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG, - "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); + ok(!ret && + (GetLastError() == CRYPT_E_ASN1_BADTAG || + GetLastError() == TRUST_E_NOSIGNATURE /* Vista */), + "Expected CRYPT_E_ASN1_BADTAG or TRUST_E_NOSIGNATURE, got %08x\n", GetLastError()); /* but not as a X509_PUBLIC_KEY_INFO.. */ certInfo.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL; certInfo.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(encodedPubKey); certInfo.SubjectPublicKeyInfo.PublicKey.pbData = encodedPubKey; SetLastError(0xdeadbeef); ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo); - ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG, - "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); + ok(!ret && + (GetLastError() == CRYPT_E_ASN1_BADTAG || + GetLastError() == TRUST_E_NOSIGNATURE /* Vista */), + "Expected CRYPT_E_ASN1_BADTAG or TRUST_E_NOSIGNATURE, got %08x\n", GetLastError()); /* This decodes successfully, but it doesn't match any key in the message */ certInfo.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(mod_encoded); certInfo.SubjectPublicKeyInfo.PublicKey.pbData = mod_encoded; @@ -2490,8 +2499,10 @@ static void test_msg_control(void) * now. */ todo_wine - ok(!ret && GetLastError() == NTE_BAD_SIGNATURE, - "Expected NTE_BAD_SIGNATURE, got %08x\n", GetLastError()); + ok(!ret && + (GetLastError() == NTE_BAD_SIGNATURE || + GetLastError() == TRUST_E_NOSIGNATURE /* Vista */), + "Expected NTE_BAD_SIGNATURE or TRUST_E_NOSIGNATURE, got %08x\n", GetLastError()); CryptMsgClose(msg); /* A message with no data doesn't have a valid signature */ msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL); @@ -2502,8 +2513,10 @@ static void test_msg_control(void) certInfo.SubjectPublicKeyInfo.PublicKey.pbData = pubKey; SetLastError(0xdeadbeef); ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo); - ok(!ret && GetLastError() == NTE_BAD_SIGNATURE, - "Expected NTE_BAD_SIGNATURE, got %08x\n", GetLastError()); + ok(!ret && + (GetLastError() == NTE_BAD_SIGNATURE || + GetLastError() == TRUST_E_NOSIGNATURE /* Vista */), + "Expected NTE_BAD_SIGNATURE or TRUST_E_NOSIGNATURE, got %08x\n", GetLastError()); CryptMsgClose(msg); /* Finally, this succeeds */ msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL); @@ -2514,182 +2527,6 @@ static void test_msg_control(void) CryptMsgClose(msg); } -static void test_msg_get_signer_count(void) -{ - LONG count; - - SetLastError(0xdeadbeef); - count = CryptGetMessageSignerCount(0, NULL, 0); - ok(count == -1, "Expected -1, got %d\n", count); - ok(GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", - GetLastError()); - SetLastError(0xdeadbeef); - count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, NULL, 0); - ok(count == -1, "Expected -1, got %d\n", count); - ok(GetLastError() == CRYPT_E_ASN1_EOD, - "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError()); - SetLastError(0xdeadbeef); - count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, - dataEmptyBareContent, sizeof(dataEmptyBareContent)); - ok(count == -1, "Expected -1, got %d\n", count); - ok(GetLastError() == CRYPT_E_ASN1_BADTAG, - "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); - SetLastError(0xdeadbeef); - count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, - dataEmptyContent, sizeof(dataEmptyContent)); - ok(count == -1, "Expected -1, got %d\n", count); - ok(GetLastError() == CRYPT_E_INVALID_MSG_TYPE, - "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError()); - SetLastError(0xdeadbeef); - count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, - signedEmptyBareContent, sizeof(signedEmptyBareContent)); - ok(count == -1, "Expected -1, got %d\n", count); - ok(GetLastError() == CRYPT_E_ASN1_BADTAG, - "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); - count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, - signedEmptyContent, sizeof(signedEmptyContent)); - ok(count == 1, "Expected 1, got %d\n", count); -} - -static const BYTE signedWithCertEmptyContent[] = { -0x30,0x81,0xdf,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0, -0x81,0xd1,0x30,0x81,0xce,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a, -0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c, -0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11, -0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, -0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30, -0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30, -0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06, -0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67, -0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30, -0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01, -0xff,0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15, -0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e, -0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86, -0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04, -0x00 }; -static const BYTE signedWithCertContent[] = { -0x30,0x82,0x01,0x32,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02, -0xa0,0x82,0x01,0x23,0x30,0x82,0x01,0x1f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c, -0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06, -0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01, -0x02,0x03,0x04,0xa0,0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30, -0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61, -0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31, -0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36, -0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15, -0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e, -0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00, -0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04, -0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01, -0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13, -0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30, -0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04, -0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1, -0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9, -0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11, -0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19, -0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d }; -static const BYTE signedWithCertWithPubKeyContent[] = { -0x30,0x81,0xfc,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0, -0x81,0xee,0x30,0x81,0xeb,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a, -0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x81, -0x98,0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13, -0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c, -0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30, -0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30, -0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30, -0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61, -0x6e,0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d, -0x01,0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06, -0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12, -0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff, -0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31, -0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20, -0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48, -0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 }; - -static void test_verify_message_signature(void) -{ - BOOL ret; - CRYPT_VERIFY_MESSAGE_PARA para = { 0 }; - PCCERT_CONTEXT cert; - DWORD cbDecoded; - - SetLastError(0xdeadbeef); - ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, 0, NULL); - ok(!ret && GetLastError() == E_INVALIDARG, - "Expected E_INVALIDARG, got %08x\n", GetLastError()); - SetLastError(0xdeadbeef); - ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL); - ok(!ret && GetLastError() == E_INVALIDARG, - "Expected E_INVALIDARG, got %08x\n", GetLastError()); - para.cbSize = sizeof(para); - SetLastError(0xdeadbeef); - ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL); - ok(!ret && GetLastError() == E_INVALIDARG, - "Expected E_INVALIDARG, got %08x\n", GetLastError()); - para.cbSize = 0; - para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING; - SetLastError(0xdeadbeef); - ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL); - ok(!ret && GetLastError() == E_INVALIDARG, - "Expected E_INVALIDARG, got %08x\n", GetLastError()); - para.cbSize = sizeof(para); - SetLastError(0xdeadbeef); - ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL); - ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD, - "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError()); - /* Check whether cert is set on error */ - cert = (PCCERT_CONTEXT)0xdeadbeef; - ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, &cert); - ok(cert == NULL, "Expected NULL cert\n"); - /* Check whether cbDecoded is set on error */ - cbDecoded = 0xdeadbeef; - ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, &cbDecoded, - NULL); - ok(!cbDecoded, "Expected 0\n"); - SetLastError(0xdeadbeef); - ret = CryptVerifyMessageSignature(¶, 0, dataEmptyBareContent, - sizeof(dataEmptyBareContent), NULL, 0, NULL); - ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG, - "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); - SetLastError(0xdeadbeef); - ret = CryptVerifyMessageSignature(¶, 0, dataEmptyContent, - sizeof(dataEmptyContent), NULL, 0, NULL); - ok(!ret && GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE, - "Expected CRYPT_E_UNEXPECTED_MSG_TYPE, got %08x\n", GetLastError()); - SetLastError(0xdeadbeef); - ret = CryptVerifyMessageSignature(¶, 0, signedEmptyBareContent, - sizeof(signedEmptyBareContent), NULL, 0, NULL); - ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG, - "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError()); - SetLastError(0xdeadbeef); - ret = CryptVerifyMessageSignature(¶, 0, signedEmptyContent, - sizeof(signedEmptyContent), NULL, 0, NULL); - ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, - "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); - SetLastError(0xdeadbeef); - ret = CryptVerifyMessageSignature(¶, 0, signedContent, - sizeof(signedContent), NULL, 0, NULL); - ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND, - "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError()); - /* FIXME: Windows fails with CRYPT_E_NOT_FOUND for these messages, but - * their signer certs have invalid public keys that fail to decode. In - * Wine therefore the failure is an ASN error. Need some messages with - * valid public keys and invalid signatures to check against. - */ - ret = CryptVerifyMessageSignature(¶, 0, signedWithCertEmptyContent, - sizeof(signedWithCertEmptyContent), NULL, 0, NULL); - ok(!ret, "Expected failure\n"); - ret = CryptVerifyMessageSignature(¶, 0, signedWithCertContent, - sizeof(signedWithCertContent), NULL, 0, NULL); - ok(!ret, "Expected failure\n"); - ret = CryptVerifyMessageSignature(¶, 0, signedWithCertWithPubKeyContent, - sizeof(signedWithCertWithPubKeyContent), NULL, 0, NULL); - ok(!ret, "Expected failure\n"); -} - /* win9x has much less parameter checks and will crash on many tests * this code is from test_signed_msg_update() */ @@ -2741,8 +2578,4 @@ START_TEST(msg) test_hash_msg(); test_signed_msg(); test_decode_msg(); - - /* simplified message functions */ - test_msg_get_signer_count(); - test_verify_message_signature(); } diff --git a/dlls/crypt32/tests/sip.c b/dlls/crypt32/tests/sip.c index b01229c0ce4..7ffa2b98d10 100644 --- a/dlls/crypt32/tests/sip.c +++ b/dlls/crypt32/tests/sip.c @@ -266,8 +266,28 @@ static void test_SIPRetrieveSubjectGUID(void) /* Clean up */ DeleteFileA(tempfile); + /* Create a file with just the .cab header 'MSCF' */ + SetLastError(0xdeadbeef); + file = CreateFileA(tempfile, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); + ok(file != INVALID_HANDLE_VALUE, "failed with %u\n", GetLastError()); + WriteFile(file, cabFileData, 4, &written, NULL); + CloseHandle(file); + + SetLastError(0xdeadbeef); + memset(&subject, 1, sizeof(GUID)); + ret = CryptSIPRetrieveSubjectGuid(tempfileW, NULL, &subject); + ok( ret, "CryptSIPRetrieveSubjectGuid failed: %d (0x%08x)\n", + GetLastError(), GetLastError() ); + ok ( !memcmp(&subject, &cabGUID, sizeof(GUID)), + "Expected GUID %s for cabinet file, not %s\n", show_guid(&cabGUID, guid1), show_guid(&subject, guid2)); + + /* Clean up */ + DeleteFileA(tempfile); + /* Create a .cab file */ - file = CreateFileW(tempfileW, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); + SetLastError(0xdeadbeef); + file = CreateFileA(tempfile, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); + ok(file != INVALID_HANDLE_VALUE, "failed with %u\n", GetLastError()); WriteFile(file, cabFileData, sizeof(cabFileData), &written, NULL); CloseHandle(file); @@ -278,8 +298,9 @@ static void test_SIPRetrieveSubjectGUID(void) GetLastError(), GetLastError() ); ok ( !memcmp(&subject, &cabGUID, sizeof(GUID)), "Expected GUID %s for cabinet file, not %s\n", show_guid(&cabGUID, guid1), show_guid(&subject, guid2)); + /* Clean up */ - DeleteFileW(tempfileW); + DeleteFileA(tempfile); } static void test_SIPLoad(void) @@ -289,7 +310,7 @@ static void test_SIPLoad(void) static GUID dummySubject = { 0xdeadbeef, 0xdead, 0xbeef, { 0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef }}; static GUID unknown = { 0xC689AABA, 0x8E78, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; /* WINTRUST.DLL */ static GUID unknown2 = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; /* WINTRUST.DLL */ - /* The next SIP is available on Windows (not on a clean Wine install) */ + /* The next SIP is available on Windows and on Wine */ static GUID unknown3 = { 0x000C10F1, 0x0000, 0x0000, { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }}; /* MSISIP.DLL */ SIP_DISPATCH_INFO sdi; HMODULE hCrypt; @@ -382,24 +403,21 @@ static void test_SIPLoad(void) /* As msisip.dll is not checked yet by any of the previous calls, the * function DllCanUnloadNow will be checked again in msisip.dll (it's not present) */ - todo_wine - { - ok( sdi.pfGet != (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected a function pointer to be loaded.\n"); - - /* This is another SIP but this test proves the function addresses are the same as - * in the previous test. - */ - if (funcCryptSIPGetSignedDataMsg && funcCryptSIPPutSignedDataMsg && funcCryptSIPCreateIndirectData && - funcCryptSIPVerifyIndirectData && funcCryptSIPRemoveSignedDataMsg) - ok (sdi.pfGet == funcCryptSIPGetSignedDataMsg && - sdi.pfPut == funcCryptSIPPutSignedDataMsg && - sdi.pfCreate == funcCryptSIPCreateIndirectData && - sdi.pfVerify == funcCryptSIPVerifyIndirectData && - sdi.pfRemove == funcCryptSIPRemoveSignedDataMsg, - "Expected function addresses to be from crypt32\n"); - else - trace("Couldn't load function pointers\n"); - } + ok( sdi.pfGet != (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected a function pointer to be loaded.\n"); + + /* This is another SIP but this test proves the function addresses are the same as + * in the previous test. + */ + if (funcCryptSIPGetSignedDataMsg && funcCryptSIPPutSignedDataMsg && funcCryptSIPCreateIndirectData && + funcCryptSIPVerifyIndirectData && funcCryptSIPRemoveSignedDataMsg) + ok (sdi.pfGet == funcCryptSIPGetSignedDataMsg && + sdi.pfPut == funcCryptSIPPutSignedDataMsg && + sdi.pfCreate == funcCryptSIPCreateIndirectData && + sdi.pfVerify == funcCryptSIPVerifyIndirectData && + sdi.pfRemove == funcCryptSIPRemoveSignedDataMsg, + "Expected function addresses to be from crypt32\n"); + else + trace("Couldn't load function pointers\n"); } /* Reserved parameter not 0 */ diff --git a/dlls/d3dx8/mesh.c b/dlls/d3dx8/mesh.c index db490d44bf5..6846d5da982 100644 --- a/dlls/d3dx8/mesh.c +++ b/dlls/d3dx8/mesh.c @@ -27,13 +27,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3dx); BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *pcenter, FLOAT radius, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection) { D3DXVECTOR3 difference; - FLOAT a, b, c; + FLOAT a, b, c, d; a = D3DXVec3LengthSq(praydirection); if (!D3DXVec3Subtract(&difference, prayposition, pcenter)) return FALSE; b = D3DXVec3Dot(&difference, praydirection); c = D3DXVec3LengthSq(&difference) - radius * radius; + d = b * b - a * c; - if ( b * b - a * c <= 0.0f ) return FALSE; + if ( ( d <= 0.0f ) || ( sqrt(d) <= b ) ) return FALSE; return TRUE; } diff --git a/dlls/d3dx8/tests/mesh.c b/dlls/d3dx8/tests/mesh.c index 8f07b079d8f..5a5eb676981 100644 --- a/dlls/d3dx8/tests/mesh.c +++ b/dlls/d3dx8/tests/mesh.c @@ -36,6 +36,10 @@ static void D3DXBoundProbeTest(void) result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); ok(result == TRUE, "expected TRUE, received FALSE\n"); + rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f; + result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); + ok(result == FALSE, "expected FALSE, received TRUE\n"); + rayposition.x = 5.0f; rayposition.y = 7.0f; rayposition.z = 9.0f; result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); ok(result == FALSE, "expected FALSE, received TRUE\n"); diff --git a/dlls/d3dx9_36/Makefile.in b/dlls/d3dx9_36/Makefile.in index 78cfd97a78f..0b5a3d3ac0d 100644 --- a/dlls/d3dx9_36/Makefile.in +++ b/dlls/d3dx9_36/Makefile.in @@ -10,7 +10,8 @@ C_SRCS = \ d3dx9_36_main.c \ font.c \ math.c \ - shader.c + shader.c \ + sprite.c RC_SRCS = version.rc diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec index 319303387ba..bf9c8f8c732 100644 --- a/dlls/d3dx9_36/d3dx9_36.spec +++ b/dlls/d3dx9_36/d3dx9_36.spec @@ -88,7 +88,7 @@ @ stub D3DXCreateSkinInfoFromBlendedMesh @ stub D3DXCreateSkinInfoFVF @ stub D3DXCreateSphere -@ stub D3DXCreateSprite +@ stdcall D3DXCreateSprite(ptr ptr) @ stub D3DXCreateTeapot @ stub D3DXCreateTextA @ stub D3DXCreateTextW diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h index 33d83b28374..e1c266da76f 100644 --- a/dlls/d3dx9_36/d3dx9_36_private.h +++ b/dlls/d3dx9_36/d3dx9_36_private.h @@ -29,12 +29,21 @@ typedef struct ID3DXFontImpl { - /* IUnknown fields */ - const ID3DXFontVtbl *lpVtbl; - LONG ref; + /* IUnknown fields */ + const ID3DXFontVtbl *lpVtbl; + LONG ref; - /* ID3DXFont fields */ + /* ID3DXFont fields */ } ID3DXFontImpl; +typedef struct ID3DXSpriteImpl +{ + /* IUnknown fields */ + const ID3DXSpriteVtbl *lpVtbl; + LONG ref; + + /* ID3DXSprite fields */ +} ID3DXSpriteImpl; + #endif /* __WINE_D3DX9_36_PRIVATE_H */ diff --git a/dlls/d3dx9_36/font.c b/dlls/d3dx9_36/font.c index 19d1638fb39..46d0fde3119 100644 --- a/dlls/d3dx9_36/font.c +++ b/dlls/d3dx9_36/font.c @@ -231,6 +231,9 @@ HRESULT WINAPI D3DXCreateFontW(LPDIRECT3DDEVICE9 device, INT height, UINT width, return D3DXCreateFontIndirectW(device, &desc, font); } +/*********************************************************************** + * D3DXCreateFontIndirectA (D3DX9_36.@) + */ HRESULT WINAPI D3DXCreateFontIndirectA(LPDIRECT3DDEVICE9 device, CONST D3DXFONT_DESCA *desc, LPD3DXFONT *font) { D3DXFONT_DESCW widedesc; @@ -246,6 +249,9 @@ HRESULT WINAPI D3DXCreateFontIndirectA(LPDIRECT3DDEVICE9 device, CONST D3DXFONT_ return D3DXCreateFontIndirectW(device, &widedesc, font); } +/*********************************************************************** + * D3DXCreateFontIndirectW (D3DX9_36.@) + */ HRESULT WINAPI D3DXCreateFontIndirectW(LPDIRECT3DDEVICE9 device, CONST D3DXFONT_DESCW *desc, LPD3DXFONT *font) { ID3DXFontImpl *object; diff --git a/dlls/d3dx9_36/sprite.c b/dlls/d3dx9_36/sprite.c new file mode 100644 index 00000000000..db977613fb9 --- /dev/null +++ b/dlls/d3dx9_36/sprite.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2008 Tony Wasserka + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#include "wine/debug.h" +#include "d3dx9_36_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3dx); + +static HRESULT WINAPI ID3DXSpriteImpl_QueryInterface(LPD3DXSPRITE iface, REFIID riid, LPVOID *object) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + + TRACE("(%p): QueryInterface from %s\n", This, debugstr_guid(riid)); + if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ID3DXSprite)) { + IUnknown_AddRef(iface); + *object=This; + return S_OK; + } + WARN("(%p)->(%s, %p): not found\n", iface, debugstr_guid(riid), *object); + return E_NOINTERFACE; +} + +static ULONG WINAPI ID3DXSpriteImpl_AddRef(LPD3DXSPRITE iface) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + ULONG ref=InterlockedIncrement(&This->ref); + TRACE("(%p): AddRef from %d\n", This, ref-1); + return ref; +} + +static ULONG WINAPI ID3DXSpriteImpl_Release(LPD3DXSPRITE iface) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + ULONG ref=InterlockedDecrement(&This->ref); + TRACE("(%p): ReleaseRef to %d\n", This, ref); + + if(ref==0) { + HeapFree(GetProcessHeap(), 0, This); + } + return ref; +} + +static HRESULT WINAPI ID3DXSpriteImpl_GetDevice(LPD3DXSPRITE iface, LPDIRECT3DDEVICE9 *device) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXSpriteImpl_GetTransform(LPD3DXSPRITE iface, D3DXMATRIX *transform) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXSpriteImpl_SetTransform(LPD3DXSPRITE iface, CONST D3DXMATRIX *transform) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXSpriteImpl_SetWorldViewRH(LPD3DXSPRITE iface, CONST D3DXMATRIX *world, CONST D3DXMATRIX *view) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXSpriteImpl_SetWorldViewLH(LPD3DXSPRITE iface, CONST D3DXMATRIX *world, CONST D3DXMATRIX *view) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXSpriteImpl_Begin(LPD3DXSPRITE iface, DWORD flags) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXSpriteImpl_Draw(LPD3DXSPRITE iface, LPDIRECT3DTEXTURE9 texture, CONST RECT *rect, CONST D3DXVECTOR3 *center, + CONST D3DXVECTOR3 *position, D3DCOLOR color) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXSpriteImpl_Flush(LPD3DXSPRITE iface) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXSpriteImpl_End(LPD3DXSPRITE iface) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXSpriteImpl_OnLostDevice(LPD3DXSPRITE iface) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXSpriteImpl_OnResetDevice(LPD3DXSPRITE iface) +{ + ID3DXSpriteImpl *This=(ID3DXSpriteImpl*)iface; + FIXME("(%p): stub\n", This); + return E_NOTIMPL; +} + +static const ID3DXSpriteVtbl D3DXSprite_Vtbl = +{ + /*** IUnknown methods ***/ + ID3DXSpriteImpl_QueryInterface, + ID3DXSpriteImpl_AddRef, + ID3DXSpriteImpl_Release, + /*** ID3DXSprite methods ***/ + ID3DXSpriteImpl_GetDevice, + ID3DXSpriteImpl_GetTransform, + ID3DXSpriteImpl_SetTransform, + ID3DXSpriteImpl_SetWorldViewRH, + ID3DXSpriteImpl_SetWorldViewLH, + ID3DXSpriteImpl_Begin, + ID3DXSpriteImpl_Draw, + ID3DXSpriteImpl_Flush, + ID3DXSpriteImpl_End, + ID3DXSpriteImpl_OnLostDevice, + ID3DXSpriteImpl_OnResetDevice +}; + +HRESULT WINAPI D3DXCreateSprite(LPDIRECT3DDEVICE9 device, LPD3DXSPRITE *sprite) +{ + ID3DXSpriteImpl *object; + + FIXME("stub\n"); + + if(device==NULL || sprite==NULL) return D3DERR_INVALIDCALL; + + object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ID3DXSpriteImpl)); + if(object==NULL) { + *sprite=NULL; + return E_OUTOFMEMORY; + } + object->lpVtbl=&D3DXSprite_Vtbl; + object->ref=1; + + *sprite=(ID3DXSprite*)object; + + return D3D_OK; +} diff --git a/dlls/d3dxof/main.c b/dlls/d3dxof/main.c index 432109aa822..e347d9e8af0 100644 --- a/dlls/d3dxof/main.c +++ b/dlls/d3dxof/main.c @@ -184,9 +184,9 @@ HRESULT WINAPI DirectXFileCreate(LPDIRECTXFILE* lplpDirectXFile) */ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) { - int i; + unsigned int i; IClassFactoryImpl *factory; - + TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); if ( !IsEqualGUID( &IID_IClassFactory, riid ) diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 6a3ecfcffae..b154ce47b7c 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -6289,7 +6289,7 @@ static void copy_mipmap_chain(IDirect3DDeviceImpl *device, if (src_level->surface_desc.dwWidth == dest_level->surface_desc.dwWidth && src_level->surface_desc.dwHeight == dest_level->surface_desc.dwHeight) { - /* Try UpdateSurface that may perform a more direct opengl loading. But skip this is destination is paletted texture and has no palette. + /* Try UpdateSurface that may perform a more direct opengl loading. But skip this if destination is paletted texture and has no palette. * Some games like Sacrifice set palette after Load, and it is a waste of effort to try to load texture without palette and generates * warnings in wined3d. */ if (!palette_missing) diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 54fefbeb4b6..7d9f72843b1 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -265,11 +265,13 @@ DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name, } /* Conversion between internal data buffer and external data buffer */ -void fill_DataFormat(void *out, const void *in, const DataFormat *df) { +void fill_DataFormat(void *out, DWORD size, const void *in, const DataFormat *df) +{ int i; const char *in_c = in; char *out_c = (char *) out; + memset(out, 0, size); if (df->dt == NULL) { /* This means that the app uses Wine's internal data format */ memcpy(out, in, df->internal_format_size); diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 93212504739..7b62a50f14d 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -76,7 +76,7 @@ extern BOOL get_app_key(HKEY*, HKEY*); extern DWORD get_config_key(HKEY, HKEY, const char*, char*, DWORD); /* Routines to do DataFormat / WineFormat conversions */ -extern void fill_DataFormat(void *out, const void *in, const DataFormat *df) ; +extern void fill_DataFormat(void *out, DWORD size, const void *in, const DataFormat *df) ; extern HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *format); extern void release_DataFormat(DataFormat *df) ; extern void queue_event(LPDIRECTINPUTDEVICE8A iface, int ofs, DWORD data, DWORD time, DWORD seq); diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c index 9dead0a9c78..bcac66a338c 100644 --- a/dlls/dinput/joystick_linux.c +++ b/dlls/dinput/joystick_linux.c @@ -767,7 +767,7 @@ static HRESULT WINAPI JoystickAImpl_GetDeviceState( joy_polldev(This); /* convert and copy data to user supplied buffer */ - fill_DataFormat(ptr, &This->js, &This->base.data_format); + fill_DataFormat(ptr, len, &This->js, &This->base.data_format); return DI_OK; } diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c index aad25a47d60..a7c9c634e6a 100644 --- a/dlls/dinput/joystick_linuxinput.c +++ b/dlls/dinput/joystick_linuxinput.c @@ -802,7 +802,7 @@ static HRESULT WINAPI JoystickAImpl_GetDeviceState( joy_polldev(This); /* convert and copy data to user supplied buffer */ - fill_DataFormat(ptr, &This->js, &This->base.data_format); + fill_DataFormat(ptr, len, &This->js, &This->base.data_format); return DI_OK; } @@ -885,6 +885,26 @@ static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface, FIXME("DIPROP_AUTOCENTER(%d)\n", pd->dwData); break; } + case (DWORD)DIPROP_SATURATION: { + LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; + + if (ph->dwHow == DIPH_DEVICE) { + int i; + + TRACE("saturation(%d) all\n", pd->dwData); + for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) + This->props[i].lSaturation = pd->dwData; + } else { + int obj = find_property(&This->base.data_format, ph); + + if (obj < 0) return DIERR_OBJECTNOTFOUND; + + TRACE("saturation(%d) obj=%d\n", pd->dwData, obj); + This->props[obj].lSaturation = pd->dwData; + } + fake_current_js_state(This); + break; + } default: return IDirectInputDevice2AImpl_SetProperty(iface, rguid, ph); } @@ -977,6 +997,17 @@ static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, TRACE("deadzone(%d) obj=%d\n", pd->dwData, obj); break; } + case (DWORD) DIPROP_SATURATION: + { + LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; + int obj = find_property(&This->base.data_format, pdiph); + + if (obj < 0) return DIERR_OBJECTNOTFOUND; + + pd->dwData = This->props[obj].lSaturation; + TRACE("saturation(%d) obj=%d\n", pd->dwData, obj); + break; + } default: return IDirectInputDevice2AImpl_GetProperty(iface, rguid, pdiph); diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c index cb290f6f07a..b2c4942bdc0 100644 --- a/dlls/dinput/keyboard.c +++ b/dlls/dinput/keyboard.c @@ -283,7 +283,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState( } } - fill_DataFormat(ptr, This->DInputKeyState, &This->base.data_format); + fill_DataFormat(ptr, len, This->DInputKeyState, &This->base.data_format); LeaveCriticalSection(&This->base.crit); return DI_OK; diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c index 1dc6a0331ff..a3610573940 100644 --- a/dlls/dinput/mouse.c +++ b/dlls/dinput/mouse.c @@ -490,7 +490,7 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceState( EnterCriticalSection(&This->base.crit); /* Copy the current mouse state */ - fill_DataFormat(ptr, &(This->m_state), &This->base.data_format); + fill_DataFormat(ptr, len, &This->m_state, &This->base.data_format); /* Initialize the buffer when in relative mode */ if (!(This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS)) diff --git a/dlls/dinput/tests/keyboard.c b/dlls/dinput/tests/keyboard.c index d427e6550c9..de55d320870 100644 --- a/dlls/dinput/tests/keyboard.c +++ b/dlls/dinput/tests/keyboard.c @@ -70,20 +70,21 @@ static void acquire_tests(LPDIRECTINPUT pDI, HWND hwnd) HRESULT hr; LPDIRECTINPUTDEVICE pKeyboard; BYTE kbd_state[256]; - BYTE custom_state[4]; + LONG custom_state[6]; + int i; DIOBJECTDATAFORMAT dodf[] = { - { &GUID_Key, 0, DIDFT_MAKEINSTANCE(DIK_Q)|DIDFT_BUTTON, 0 }, - { &GUID_Key, 1, DIDFT_MAKEINSTANCE(DIK_W)|DIDFT_BUTTON, 0 }, - { &GUID_Key, 2, DIDFT_MAKEINSTANCE(DIK_E)|DIDFT_BUTTON, 0 }, - { &GUID_Key, 3, DIDFT_MAKEINSTANCE(DIK_R)|DIDFT_BUTTON, 0 }, + { &GUID_Key, sizeof(LONG) * 0, DIDFT_MAKEINSTANCE(DIK_Q)|DIDFT_BUTTON, 0 }, + { &GUID_Key, sizeof(LONG) * 1, DIDFT_MAKEINSTANCE(DIK_W)|DIDFT_BUTTON, 0 }, + { &GUID_Key, sizeof(LONG) * 2, DIDFT_MAKEINSTANCE(DIK_E)|DIDFT_BUTTON, 0 }, + { &GUID_Key, sizeof(LONG) * 4, DIDFT_MAKEINSTANCE(DIK_R)|DIDFT_BUTTON, 0 }, }; DIDATAFORMAT df; df.dwSize = sizeof( df ); df.dwObjSize = sizeof( DIOBJECTDATAFORMAT ); df.dwFlags = DIDF_RELAXIS; - df.dwDataSize = sizeof( dodf )/sizeof( dodf[0] ); + df.dwDataSize = sizeof( custom_state ); df.dwNumObjs = sizeof( dodf )/sizeof( dodf[0] ); df.rgodf = dodf; @@ -120,6 +121,11 @@ static void acquire_tests(LPDIRECTINPUT pDI, HWND hwnd) hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(kbd_state), kbd_state); ok(hr == DIERR_INVALIDPARAM, "IDirectInputDevice_GetDeviceState(256,) should have failed: %08x\n", hr); + memset(custom_state, 0x56, sizeof(custom_state)); + IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state); + for (i = 0; i < sizeof(custom_state) / sizeof(custom_state[0]); i++) + ok(custom_state[i] == 0, "Should be zeroed, got 0x%08x\n", custom_state[i]); + if (pKeyboard) IUnknown_Release(pKeyboard); } diff --git a/dlls/dmband/dmutils.c b/dlls/dmband/dmutils.c index bfec1f16e90..19cba2b84a2 100644 --- a/dlls/dmband/dmutils.c +++ b/dlls/dmband/dmutils.c @@ -63,7 +63,8 @@ BOOL IS_VALID_DMFORM (FOURCC chunkID) { /* generic flag-dumping function */ static const char* debugstr_flags (DWORD flags, const flag_info* names, size_t num_names){ static char buffer[128] = "", *ptr = &buffer[0]; - unsigned int i, size = sizeof(buffer); + unsigned int i; + int size = sizeof(buffer); for (i=0; i < num_names; i++) { if ((flags & names[i].val)) { diff --git a/dlls/dmcompos/dmcompos_main.c b/dlls/dmcompos/dmcompos_main.c index 36244debfe3..a70c292a638 100644 --- a/dlls/dmcompos/dmcompos_main.c +++ b/dlls/dmcompos/dmcompos_main.c @@ -693,7 +693,8 @@ const char *debugstr_dmreturn (DWORD code) { /* generic flag-dumping function */ const char* debugstr_flags (DWORD flags, const flag_info* names, size_t num_names){ char buffer[128] = "", *ptr = &buffer[0]; - unsigned int i, size = sizeof(buffer); + unsigned int i; + int size = sizeof(buffer); for (i=0; i < num_names; i++) { diff --git a/dlls/dmime/dmutils.c b/dlls/dmime/dmutils.c index 1a822ba1019..87668cb6f5b 100644 --- a/dlls/dmime/dmutils.c +++ b/dlls/dmime/dmutils.c @@ -617,7 +617,8 @@ const char *debugstr_dmreturn (DWORD code) { /* generic flag-dumping function */ static const char* debugstr_flags (DWORD flags, const flag_info* names, size_t num_names){ static char buffer[128] = "", *ptr = &buffer[0]; - unsigned int i, size = sizeof(buffer); + unsigned int i; + int size = sizeof(buffer); for (i=0; i < num_names; i++) { if ((flags & names[i].val)) { diff --git a/dlls/dmloader/debug.c b/dlls/dmloader/debug.c index dbd812905f7..db85d76f350 100644 --- a/dlls/dmloader/debug.c +++ b/dlls/dmloader/debug.c @@ -433,7 +433,8 @@ const char *debugstr_dmreturn (DWORD code) { /* generic flag-dumping function */ static const char* debugstr_flags (DWORD flags, const flag_info* names, size_t num_names){ static char buffer[128] = "", *ptr = &buffer[0]; - unsigned int i, size = sizeof(buffer); + unsigned int i; + int size = sizeof(buffer); for (i=0; i < num_names; i++) { if ((flags & names[i].val)) { diff --git a/dlls/dmscript/dmscript_main.c b/dlls/dmscript/dmscript_main.c index 6b6bbcd4f95..c211aa7bfae 100644 --- a/dlls/dmscript/dmscript_main.c +++ b/dlls/dmscript/dmscript_main.c @@ -977,7 +977,8 @@ const char *debugstr_dmreturn (DWORD code) { /* generic flag-dumping function */ const char* debugstr_flags (DWORD flags, const flag_info* names, size_t num_names){ char buffer[128] = "", *ptr = &buffer[0]; - unsigned int i, size = sizeof(buffer); + unsigned int i; + int size = sizeof(buffer); for (i=0; i < num_names; i++) { diff --git a/dlls/dmstyle/dmutils.c b/dlls/dmstyle/dmutils.c index ce3de4682e6..7f6d37fe4cc 100644 --- a/dlls/dmstyle/dmutils.c +++ b/dlls/dmstyle/dmutils.c @@ -628,8 +628,9 @@ const char *debugstr_dmreturn (DWORD code) { /* generic flag-dumping function */ const char* debugstr_flags (DWORD flags, const flag_info* names, size_t num_names){ static char buffer[128] = "", *ptr = &buffer[0]; - unsigned int i, size = sizeof(buffer); - + unsigned int i; + int size = sizeof(buffer); + for (i=0; i < num_names; i++) { if ((flags & names[i].val)) { int cnt = snprintf(ptr, size, "%s ", names[i].name); diff --git a/dlls/dmsynth/dmsynth_main.c b/dlls/dmsynth/dmsynth_main.c index 372bee5f715..0a525446bf3 100644 --- a/dlls/dmsynth/dmsynth_main.c +++ b/dlls/dmsynth/dmsynth_main.c @@ -525,7 +525,8 @@ const char *debugstr_dmreturn (DWORD code) { /* generic flag-dumping function */ const char* debugstr_flags (DWORD flags, const flag_info* names, size_t num_names){ char buffer[128] = "", *ptr = &buffer[0]; - unsigned int i, size = sizeof(buffer); + unsigned int i; + int size = sizeof(buffer); for (i=0; i < num_names; i++) { diff --git a/dlls/dmusic/dmusic_main.c b/dlls/dmusic/dmusic_main.c index c4a231c5d20..89f8eb1cc31 100644 --- a/dlls/dmusic/dmusic_main.c +++ b/dlls/dmusic/dmusic_main.c @@ -549,7 +549,8 @@ const char *debugstr_dmreturn (DWORD code) { /* generic flag-dumping function */ const char* debugstr_flags (DWORD flags, const flag_info* names, size_t num_names){ char buffer[128] = "", *ptr = &buffer[0]; - unsigned int i, size = sizeof(buffer); + unsigned int i; + int size = sizeof(buffer); for (i=0; i < num_names; i++) { diff --git a/dlls/dnsapi/query.c b/dlls/dnsapi/query.c index 7ca08a026b6..6c7e4c8ef9c 100644 --- a/dlls/dnsapi/query.c +++ b/dlls/dnsapi/query.c @@ -561,7 +561,7 @@ exit: */ static DNS_STATUS dns_set_serverlist( const IP4_ARRAY *addrs ) { - unsigned int i; + int i; if (addrs->AddrCount > MAXNS) { @@ -579,7 +579,8 @@ static DNS_STATUS dns_set_serverlist( const IP4_ARRAY *addrs ) static DNS_STATUS dns_get_serverlist( PIP4_ARRAY addrs, PDWORD len ) { - unsigned int i, size; + unsigned int size; + int i; size = sizeof(IP4_ARRAY) + sizeof(IP4_ADDRESS) * (_res.nscount - 1); if (!addrs || *len < size) diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 829a21c3ffa..1ba7d7e2150 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -2380,6 +2380,11 @@ static HRESULT WINAPI DP_IF_GetPlayerCaps TRACE("(%p)->(0x%08x,%p,0x%08x)\n", This, idPlayer, lpDPCaps, dwFlags); + if ( This->dp2->connectionInitialized == NO_PROVIDER ) + { + return DPERR_UNINITIALIZED; + } + /* Query the service provider */ data.idPlayer = idPlayer; data.dwFlags = dwFlags; @@ -3760,7 +3765,7 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections /* The enumeration will return FALSE if we are not to continue */ if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize, - &dpName, DPCONNECTION_DIRECTPLAY, lpContext ) ) + &dpName, dwFlags, lpContext ) ) { return DP_OK; } @@ -3868,7 +3873,7 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections /* The enumeration will return FALSE if we are not to continue */ if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize, - &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) ) + &dpName, dwFlags, lpContext ) ) { HeapFree( GetProcessHeap(), 0, lpAddressBuffer ); return DP_OK; @@ -4227,11 +4232,21 @@ static HRESULT WINAPI DP_IF_InitializeConnection TRACE("(%p)->(%p,0x%08x,%u)\n", This, lpConnection, dwFlags, bAnsi ); + if ( lpConnection == NULL ) + { + return DPERR_INVALIDPARAMS; + } + if( dwFlags != 0 ) { return DPERR_INVALIDFLAGS; } + if( This->dp2->connectionInitialized != NO_PROVIDER ) + { + return DPERR_ALREADYINITIALIZED; + } + /* Find out what the requested SP is and how large this buffer is */ hr = DPL_EnumAddress( DP_GetSpLpGuidFromCompoundAddress, lpConnection, dwAddrSize, &guidSP ); @@ -5393,7 +5408,7 @@ static BOOL CALLBACK cbDPCreateEnumConnections( * */ HRESULT WINAPI DirectPlayCreate -( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk) +( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk ) { HRESULT hr; LPDIRECTPLAY3A lpDP3A; @@ -5406,6 +5421,12 @@ HRESULT WINAPI DirectPlayCreate return CLASS_E_NOAGGREGATION; } + if( (lplpDP == NULL) || (lpGUID == NULL) ) + { + return DPERR_INVALIDPARAMS; + } + + /* Create an IDirectPlay object. We don't support that so we'll cheat and give them an IDirectPlay2A object and hope that doesn't cause problems */ if( DP_CreateInterface( &IID_IDirectPlay2A, (LPVOID*)lplpDP ) != DP_OK ) diff --git a/dlls/dplayx/regsvr.c b/dlls/dplayx/regsvr.c index cb5a5d23030..6bfc81207b8 100644 --- a/dlls/dplayx/regsvr.c +++ b/dlls/dplayx/regsvr.c @@ -32,7 +32,7 @@ #include "wine/debug.h" -WINE_DEFAULT_DEBUG_CHANNEL(dplayx); +WINE_DEFAULT_DEBUG_CHANNEL(dplay); /* * Near the bottom of this file are the exported DllRegisterServer and diff --git a/dlls/dplayx/tests/Makefile.in b/dlls/dplayx/tests/Makefile.in index b6aed257910..99672522ef5 100644 --- a/dlls/dplayx/tests/Makefile.in +++ b/dlls/dplayx/tests/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../../.. SRCDIR = @srcdir@ VPATH = @srcdir@ TESTDLL = dplayx.dll -IMPORTS = ole32 kernel32 +IMPORTS = dplayx ole32 kernel32 CTESTS = \ dplayx.c diff --git a/dlls/dplayx/tests/dplayx.c b/dlls/dplayx/tests/dplayx.c dissimilarity index 66% index 4af7f5c5810..5dccfe1c31a 100644 --- a/dlls/dplayx/tests/dplayx.c +++ b/dlls/dplayx/tests/dplayx.c @@ -1,94 +1,886 @@ -/* DirectPlay Conformance Tests - * - * Copyright 2007 - Alessandro Pignotti - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "wine/test.h" -#define INITGUID -#include - -static BOOL validSP = FALSE; /*This global variable is needed until wine has a working service provider - implementation*/ - -static BOOL CALLBACK EnumConnectionsCallback(LPCGUID lpguidSP, LPVOID lpConnection, - DWORD dwConnectionSize, LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext) -{ - HRESULT hr; - - if(IsEqualGUID(lpguidSP,&DPSPGUID_TCPIP)) - { - /*I'm forcing the TCP/IP Service provider*/ - hr = IDirectPlayX_InitializeConnection((LPDIRECTPLAY4) lpContext, lpConnection, 0); - if( SUCCEEDED( hr )) - validSP = TRUE; - return FALSE; - } - return TRUE; -} - -static void test_session_guid(LPDIRECTPLAY4 pDP) -{ - GUID appGuid; - GUID zeroGuid; - DPSESSIONDESC2 sessionDesc; - LPDPSESSIONDESC2 newSession; - DWORD sessionSize; - static char name[] = "DPlay conformance test"; - - CoCreateGuid( &appGuid ); - IDirectPlayX_EnumConnections(pDP, &appGuid, EnumConnectionsCallback, pDP, 0); - - if( !validSP ) - { - skip("Tests will not work without a valid service provider, skipping.\n"); - return; - } - - memset(&sessionDesc, 0, sizeof( DPSESSIONDESC2 )); - memset(&zeroGuid, 0, 16); - - sessionDesc.dwSize = sizeof( DPSESSIONDESC2 ); - memcpy(&sessionDesc.guidApplication, &appGuid, 16); - sessionDesc.dwFlags = DPSESSION_CLIENTSERVER; - U1(sessionDesc).lpszSessionNameA = name; - sessionDesc.dwMaxPlayers = 10; - sessionDesc.dwCurrentPlayers = 0; - IDirectPlayX_Open(pDP, &sessionDesc, DPOPEN_CREATE); - - /* I read the sessiondesc from directplay in a fresh memory location, - because directplay does not touch the original struct, but saves - internally a version with the session guid set*/ - - IDirectPlayX_GetSessionDesc(pDP, NULL, &sessionSize); - newSession = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sessionSize); - IDirectPlayX_GetSessionDesc(pDP, newSession, &sessionSize); - todo_wine ok( !IsEqualGUID(&newSession->guidInstance, &zeroGuid), "Session guid not initialized\n"); - HeapFree(GetProcessHeap(), 0, newSession); -} - -START_TEST(dplayx) -{ - LPDIRECTPLAY4 pDP; - - CoInitialize( NULL ); - CoCreateInstance(&CLSID_DirectPlay, NULL, CLSCTX_ALL, &IID_IDirectPlay4A, (VOID**)&pDP); - - test_session_guid( pDP ); - - IDirectPlayX_Release( pDP ); - CoUninitialize(); -} +/* DirectPlay Conformance Tests + * + * Copyright 2007 - Alessandro Pignotti + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wine/test.h" +#include +#define INITGUID +#include +#include + + +#define check(expected, result) \ + ok( (expected) == (result), \ + "expected=%d got=%d\n", \ + expected, result ); +#define checkHR(expected, result) \ + ok( (expected) == (result), \ + "expected=%s got=%s\n", \ + dpResult2str(expected), dpResult2str(result) ); +#define checkFlags(expected, result, flags) \ + ok( (expected) == (result), \ + "expected=0x%08x(%s) got=0x%08x(%s)\n", \ + expected, dwFlags2str(expected, flags), \ + result, dwFlags2str(result, flags) ); +#define checkGuid(expected, result) \ + ok( IsEqualGUID(expected, result), \ + "expected=%s got=%s\n", \ + Guid2str(expected), Guid2str(result) ); + + +DEFINE_GUID(appGuid, 0xbdcfe03e, 0xf0ec, 0x415b, 0x82, 0x11, 0x6f, 0x86, 0xd8, 0x19, 0x7f, 0xe1); +DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); + + +typedef struct tagCallbackData +{ + LPDIRECTPLAY4 pDP; + UINT dwCounter1, dwCounter2; + DWORD dwFlags; + char szTrace1[1024], szTrace2[1024]; + DPID *dpid; + UINT dpidSize; +} CallbackData, *lpCallbackData; + + +static LPSTR get_temp_buffer(void) +{ + static UINT index = 0; + static char buff[10][256]; + + index = (index + 1) % 10; + *buff[index] = 0; + + return buff[index]; +} + + +static LPCSTR Guid2str(const GUID *guid) +{ + LPSTR buffer = get_temp_buffer(); + + if (!guid) return "(null)"; + + /* Service providers */ + if (IsEqualGUID(guid, &DPSPGUID_IPX)) + return "DPSPGUID_IPX"; + if (IsEqualGUID(guid, &DPSPGUID_TCPIP)) + return "DPSPGUID_TCPIP"; + if (IsEqualGUID(guid, &DPSPGUID_SERIAL)) + return "DPSPGUID_SERIAL"; + if (IsEqualGUID(guid, &DPSPGUID_MODEM)) + return "DPSPGUID_MODEM"; + /* DirectPlay Address ID's */ + if (IsEqualGUID(guid, &DPAID_TotalSize)) + return "DPAID_TotalSize"; + if (IsEqualGUID(guid, &DPAID_ServiceProvider)) + return "DPAID_ServiceProvider"; + if (IsEqualGUID(guid, &DPAID_LobbyProvider)) + return "DPAID_LobbyProvider"; + if (IsEqualGUID(guid, &DPAID_Phone)) + return "DPAID_Phone"; + if (IsEqualGUID(guid, &DPAID_PhoneW)) + return "DPAID_PhoneW"; + if (IsEqualGUID(guid, &DPAID_Modem)) + return "DPAID_Modem"; + if (IsEqualGUID(guid, &DPAID_ModemW)) + return "DPAID_ModemW"; + if (IsEqualGUID(guid, &DPAID_INet)) + return "DPAID_INet"; + if (IsEqualGUID(guid, &DPAID_INetW)) + return "DPAID_INetW"; + if (IsEqualGUID(guid, &DPAID_INetPort)) + return "DPAID_INetPort"; + if (IsEqualGUID(guid, &DPAID_ComPort)) + return "DPAID_ComPort"; + + sprintf( buffer, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], + guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] ); + return buffer; + +} + + +static LPCSTR dpResult2str(HRESULT hr) +{ + switch (hr) + { + case DP_OK: return "DP_OK"; + case DPERR_ALREADYINITIALIZED: return "DPERR_ALREADYINITIALIZED"; + case DPERR_ACCESSDENIED: return "DPERR_ACCESSDENIED"; + case DPERR_ACTIVEPLAYERS: return "DPERR_ACTIVEPLAYERS"; + case DPERR_BUFFERTOOSMALL: return "DPERR_BUFFERTOOSMALL"; + case DPERR_CANTADDPLAYER: return "DPERR_CANTADDPLAYER"; + case DPERR_CANTCREATEGROUP: return "DPERR_CANTCREATEGROUP"; + case DPERR_CANTCREATEPLAYER: return "DPERR_CANTCREATEPLAYER"; + case DPERR_CANTCREATESESSION: return "DPERR_CANTCREATESESSION"; + case DPERR_CAPSNOTAVAILABLEYET: return "DPERR_CAPSNOTAVAILABLEYET"; + case DPERR_EXCEPTION: return "DPERR_EXCEPTION"; + case DPERR_GENERIC: return "DPERR_GENERIC"; + case DPERR_INVALIDFLAGS: return "DPERR_INVALIDFLAGS"; + case DPERR_INVALIDOBJECT: return "DPERR_INVALIDOBJECT"; + case DPERR_INVALIDPARAMS: return "DPERR_INVALIDPARAMS"; + /* symbol with the same value: DPERR_INVALIDPARAM */ + case DPERR_INVALIDPLAYER: return "DPERR_INVALIDPLAYER"; + case DPERR_INVALIDGROUP: return "DPERR_INVALIDGROUP"; + case DPERR_NOCAPS: return "DPERR_NOCAPS"; + case DPERR_NOCONNECTION: return "DPERR_NOCONNECTION"; + case DPERR_NOMEMORY: return "DPERR_NOMEMORY"; + /* symbol with the same value: DPERR_OUTOFMEMORY */ + case DPERR_NOMESSAGES: return "DPERR_NOMESSAGES"; + case DPERR_NONAMESERVERFOUND: return "DPERR_NONAMESERVERFOUND"; + case DPERR_NOPLAYERS: return "DPERR_NOPLAYERS"; + case DPERR_NOSESSIONS: return "DPERR_NOSESSIONS"; + case DPERR_PENDING: return "DPERR_PENDING"; + case DPERR_SENDTOOBIG: return "DPERR_SENDTOOBIG"; + case DPERR_TIMEOUT: return "DPERR_TIMEOUT"; + case DPERR_UNAVAILABLE: return "DPERR_UNAVAILABLE"; + case DPERR_UNSUPPORTED: return "DPERR_UNSUPPORTED"; + case DPERR_BUSY: return "DPERR_BUSY"; + case DPERR_USERCANCEL: return "DPERR_USERCANCEL"; + case DPERR_NOINTERFACE: return "DPERR_NOINTERFACE"; + case DPERR_CANNOTCREATESERVER: return "DPERR_CANNOTCREATESERVER"; + case DPERR_PLAYERLOST: return "DPERR_PLAYERLOST"; + case DPERR_SESSIONLOST: return "DPERR_SESSIONLOST"; + case DPERR_UNINITIALIZED: return "DPERR_UNINITIALIZED"; + case DPERR_NONEWPLAYERS: return "DPERR_NONEWPLAYERS"; + case DPERR_INVALIDPASSWORD: return "DPERR_INVALIDPASSWORD"; + case DPERR_CONNECTING: return "DPERR_CONNECTING"; + case DPERR_CONNECTIONLOST: return "DPERR_CONNECTIONLOST"; + case DPERR_UNKNOWNMESSAGE: return "DPERR_UNKNOWNMESSAGE"; + case DPERR_CANCELFAILED: return "DPERR_CANCELFAILED"; + case DPERR_INVALIDPRIORITY: return "DPERR_INVALIDPRIORITY"; + case DPERR_NOTHANDLED: return "DPERR_NOTHANDLED"; + case DPERR_CANCELLED: return "DPERR_CANCELLED"; + case DPERR_ABORTED: return "DPERR_ABORTED"; + case DPERR_BUFFERTOOLARGE: return "DPERR_BUFFERTOOLARGE"; + case DPERR_CANTCREATEPROCESS: return "DPERR_CANTCREATEPROCESS"; + case DPERR_APPNOTSTARTED: return "DPERR_APPNOTSTARTED"; + case DPERR_INVALIDINTERFACE: return "DPERR_INVALIDINTERFACE"; + case DPERR_NOSERVICEPROVIDER: return "DPERR_NOSERVICEPROVIDER"; + case DPERR_UNKNOWNAPPLICATION: return "DPERR_UNKNOWNAPPLICATION"; + case DPERR_NOTLOBBIED: return "DPERR_NOTLOBBIED"; + case DPERR_SERVICEPROVIDERLOADED: return "DPERR_SERVICEPROVIDERLOADED"; + case DPERR_ALREADYREGISTERED: return "DPERR_ALREADYREGISTERED"; + case DPERR_NOTREGISTERED: return "DPERR_NOTREGISTERED"; + case DPERR_AUTHENTICATIONFAILED: return "DPERR_AUTHENTICATIONFAILED"; + case DPERR_CANTLOADSSPI: return "DPERR_CANTLOADSSPI"; + case DPERR_ENCRYPTIONFAILED: return "DPERR_ENCRYPTIONFAILED"; + case DPERR_SIGNFAILED: return "DPERR_SIGNFAILED"; + case DPERR_CANTLOADSECURITYPACKAGE: return "DPERR_CANTLOADSECURITYPACKAGE"; + case DPERR_ENCRYPTIONNOTSUPPORTED: return "DPERR_ENCRYPTIONNOTSUPPORTED"; + case DPERR_CANTLOADCAPI: return "DPERR_CANTLOADCAPI"; + case DPERR_NOTLOGGEDIN: return "DPERR_NOTLOGGEDIN"; + case DPERR_LOGONDENIED: return "DPERR_LOGONDENIED"; + case CLASS_E_NOAGGREGATION: return "CLASS_E_NOAGGREGATION"; + + default: + { + LPSTR buffer = get_temp_buffer(); + sprintf( buffer, "%d", HRESULT_CODE(hr) ); + return buffer; + } + } +} + +static LPCSTR dwFlags2str(DWORD dwFlags, DWORD flagType) +{ + +#define FLAGS_DPCONNECTION (1<<0) +#define FLAGS_DPENUMPLAYERS (1<<1) +#define FLAGS_DPENUMGROUPS (1<<2) +#define FLAGS_DPPLAYER (1<<3) +#define FLAGS_DPGROUP (1<<4) +#define FLAGS_DPENUMSESSIONS (1<<5) +#define FLAGS_DPGETCAPS (1<<6) +#define FLAGS_DPGET (1<<7) +#define FLAGS_DPRECEIVE (1<<8) +#define FLAGS_DPSEND (1<<9) +#define FLAGS_DPSET (1<<10) +#define FLAGS_DPMESSAGEQUEUE (1<<11) +#define FLAGS_DPCONNECT (1<<12) +#define FLAGS_DPOPEN (1<<13) +#define FLAGS_DPSESSION (1<<14) +#define FLAGS_DPLCONNECTION (1<<15) +#define FLAGS_DPESC (1<<16) +#define FLAGS_DPCAPS (1<<17) + + LPSTR flags = get_temp_buffer(); + + /* EnumConnections */ + + if (flagType & FLAGS_DPCONNECTION) + { + if (dwFlags & DPCONNECTION_DIRECTPLAY) + strcat(flags, "DPCONNECTION_DIRECTPLAY,"); + if (dwFlags & DPCONNECTION_DIRECTPLAYLOBBY) + strcat(flags, "DPCONNECTION_DIRECTPLAYLOBBY,"); + } + + /* EnumPlayers, + EnumGroups */ + + if (flagType & FLAGS_DPENUMPLAYERS) + { + if (dwFlags == DPENUMPLAYERS_ALL) + strcat(flags, "DPENUMPLAYERS_ALL,"); + if (dwFlags & DPENUMPLAYERS_LOCAL) + strcat(flags, "DPENUMPLAYERS_LOCAL,"); + if (dwFlags & DPENUMPLAYERS_REMOTE) + strcat(flags, "DPENUMPLAYERS_REMOTE,"); + if (dwFlags & DPENUMPLAYERS_GROUP) + strcat(flags, "DPENUMPLAYERS_GROUP,"); + if (dwFlags & DPENUMPLAYERS_SESSION) + strcat(flags, "DPENUMPLAYERS_SESSION,"); + if (dwFlags & DPENUMPLAYERS_SERVERPLAYER) + strcat(flags, "DPENUMPLAYERS_SERVERPLAYER,"); + if (dwFlags & DPENUMPLAYERS_SPECTATOR) + strcat(flags, "DPENUMPLAYERS_SPECTATOR,"); + if (dwFlags & DPENUMPLAYERS_OWNER) + strcat(flags, "DPENUMPLAYERS_OWNER,"); + } + if (flagType & FLAGS_DPENUMGROUPS) + { + if (dwFlags == DPENUMGROUPS_ALL) + strcat(flags, "DPENUMGROUPS_ALL,"); + if (dwFlags & DPENUMPLAYERS_LOCAL) + strcat(flags, "DPENUMGROUPS_LOCAL,"); + if (dwFlags & DPENUMPLAYERS_REMOTE) + strcat(flags, "DPENUMGROUPS_REMOTE,"); + if (dwFlags & DPENUMPLAYERS_GROUP) + strcat(flags, "DPENUMGROUPS_GROUP,"); + if (dwFlags & DPENUMPLAYERS_SESSION) + strcat(flags, "DPENUMGROUPS_SESSION,"); + if (dwFlags & DPENUMGROUPS_SHORTCUT) + strcat(flags, "DPENUMGROUPS_SHORTCUT,"); + if (dwFlags & DPENUMGROUPS_STAGINGAREA) + strcat(flags, "DPENUMGROUPS_STAGINGAREA,"); + if (dwFlags & DPENUMGROUPS_HIDDEN) + strcat(flags, "DPENUMGROUPS_HIDDEN,"); + } + + /* CreatePlayer */ + + if (flagType & FLAGS_DPPLAYER) + { + if (dwFlags & DPPLAYER_SERVERPLAYER) + strcat(flags, "DPPLAYER_SERVERPLAYER,"); + if (dwFlags & DPPLAYER_SPECTATOR) + strcat(flags, "DPPLAYER_SPECTATOR,"); + if (dwFlags & DPPLAYER_LOCAL) + strcat(flags, "DPPLAYER_LOCAL,"); + if (dwFlags & DPPLAYER_OWNER) + strcat(flags, "DPPLAYER_OWNER,"); + } + + /* CreateGroup */ + + if (flagType & FLAGS_DPGROUP) + { + if (dwFlags & DPGROUP_STAGINGAREA) + strcat(flags, "DPGROUP_STAGINGAREA,"); + if (dwFlags & DPGROUP_LOCAL) + strcat(flags, "DPGROUP_LOCAL,"); + if (dwFlags & DPGROUP_HIDDEN) + strcat(flags, "DPGROUP_HIDDEN,"); + } + + /* EnumSessions */ + + if (flagType & FLAGS_DPENUMSESSIONS) + { + if (dwFlags & DPENUMSESSIONS_AVAILABLE) + strcat(flags, "DPENUMSESSIONS_AVAILABLE,"); + if (dwFlags & DPENUMSESSIONS_ALL) + strcat(flags, "DPENUMSESSIONS_ALL,"); + if (dwFlags & DPENUMSESSIONS_ASYNC) + strcat(flags, "DPENUMSESSIONS_ASYNC,"); + if (dwFlags & DPENUMSESSIONS_STOPASYNC) + strcat(flags, "DPENUMSESSIONS_STOPASYNC,"); + if (dwFlags & DPENUMSESSIONS_PASSWORDREQUIRED) + strcat(flags, "DPENUMSESSIONS_PASSWORDREQUIRED,"); + if (dwFlags & DPENUMSESSIONS_RETURNSTATUS) + strcat(flags, "DPENUMSESSIONS_RETURNSTATUS,"); + } + + /* GetCaps, + GetPlayerCaps */ + + if (flagType & FLAGS_DPGETCAPS) + { + if (dwFlags & DPGETCAPS_GUARANTEED) + strcat(flags, "DPGETCAPS_GUARANTEED,"); + } + + /* GetGroupData, + GetPlayerData */ + + if (flagType & FLAGS_DPGET) + { + if (dwFlags == DPGET_REMOTE) + strcat(flags, "DPGET_REMOTE,"); + if (dwFlags & DPGET_LOCAL) + strcat(flags, "DPGET_LOCAL,"); + } + + /* Receive */ + + if (flagType & FLAGS_DPRECEIVE) + { + if (dwFlags & DPRECEIVE_ALL) + strcat(flags, "DPRECEIVE_ALL,"); + if (dwFlags & DPRECEIVE_TOPLAYER) + strcat(flags, "DPRECEIVE_TOPLAYER,"); + if (dwFlags & DPRECEIVE_FROMPLAYER) + strcat(flags, "DPRECEIVE_FROMPLAYER,"); + if (dwFlags & DPRECEIVE_PEEK) + strcat(flags, "DPRECEIVE_PEEK,"); + } + + /* Send */ + + if (flagType & FLAGS_DPSEND) + { + /*if (dwFlags == DPSEND_NONGUARANTEED) + strcat(flags, "DPSEND_NONGUARANTEED,");*/ + if (dwFlags == DPSEND_MAX_PRIORITY) /* = DPSEND_MAX_PRI */ + { + strcat(flags, "DPSEND_MAX_PRIORITY,"); + } + else + { + if (dwFlags & DPSEND_GUARANTEED) + strcat(flags, "DPSEND_GUARANTEED,"); + if (dwFlags & DPSEND_HIGHPRIORITY) + strcat(flags, "DPSEND_HIGHPRIORITY,"); + if (dwFlags & DPSEND_OPENSTREAM) + strcat(flags, "DPSEND_OPENSTREAM,"); + if (dwFlags & DPSEND_CLOSESTREAM) + strcat(flags, "DPSEND_CLOSESTREAM,"); + if (dwFlags & DPSEND_SIGNED) + strcat(flags, "DPSEND_SIGNED,"); + if (dwFlags & DPSEND_ENCRYPTED) + strcat(flags, "DPSEND_ENCRYPTED,"); + if (dwFlags & DPSEND_LOBBYSYSTEMMESSAGE) + strcat(flags, "DPSEND_LOBBYSYSTEMMESSAGE,"); + if (dwFlags & DPSEND_ASYNC) + strcat(flags, "DPSEND_ASYNC,"); + if (dwFlags & DPSEND_NOSENDCOMPLETEMSG) + strcat(flags, "DPSEND_NOSENDCOMPLETEMSG,"); + } + } + + /* SetGroupData, + SetGroupName, + SetPlayerData, + SetPlayerName, + SetSessionDesc */ + + if (flagType & FLAGS_DPSET) + { + if (dwFlags == DPSET_REMOTE) + strcat(flags, "DPSET_REMOTE,"); + if (dwFlags & DPSET_LOCAL) + strcat(flags, "DPSET_LOCAL,"); + if (dwFlags & DPSET_GUARANTEED) + strcat(flags, "DPSET_GUARANTEED,"); + } + + /* GetMessageQueue */ + + if (flagType & FLAGS_DPMESSAGEQUEUE) + { + if (dwFlags & DPMESSAGEQUEUE_SEND) + strcat(flags, "DPMESSAGEQUEUE_SEND,"); + if (dwFlags & DPMESSAGEQUEUE_RECEIVE) + strcat(flags, "DPMESSAGEQUEUE_RECEIVE,"); + } + + /* Connect */ + + if (flagType & FLAGS_DPCONNECT) + { + if (dwFlags & DPCONNECT_RETURNSTATUS) + strcat(flags, "DPCONNECT_RETURNSTATUS,"); + } + + /* Open */ + + if (flagType & FLAGS_DPOPEN) + { + if (dwFlags & DPOPEN_JOIN) + strcat(flags, "DPOPEN_JOIN,"); + if (dwFlags & DPOPEN_CREATE) + strcat(flags, "DPOPEN_CREATE,"); + if (dwFlags & DPOPEN_RETURNSTATUS) + strcat(flags, "DPOPEN_RETURNSTATUS,"); + } + + /* DPSESSIONDESC2 */ + + if (flagType & FLAGS_DPSESSION) + { + if (dwFlags & DPSESSION_NEWPLAYERSDISABLED) + strcat(flags, "DPSESSION_NEWPLAYERSDISABLED,"); + if (dwFlags & DPSESSION_MIGRATEHOST) + strcat(flags, "DPSESSION_MIGRATEHOST,"); + if (dwFlags & DPSESSION_NOMESSAGEID) + strcat(flags, "DPSESSION_NOMESSAGEID,"); + if (dwFlags & DPSESSION_JOINDISABLED) + strcat(flags, "DPSESSION_JOINDISABLED,"); + if (dwFlags & DPSESSION_KEEPALIVE) + strcat(flags, "DPSESSION_KEEPALIVE,"); + if (dwFlags & DPSESSION_NODATAMESSAGES) + strcat(flags, "DPSESSION_NODATAMESSAGES,"); + if (dwFlags & DPSESSION_SECURESERVER) + strcat(flags, "DPSESSION_SECURESERVER,"); + if (dwFlags & DPSESSION_PRIVATE) + strcat(flags, "DPSESSION_PRIVATE,"); + if (dwFlags & DPSESSION_PASSWORDREQUIRED) + strcat(flags, "DPSESSION_PASSWORDREQUIRED,"); + if (dwFlags & DPSESSION_MULTICASTSERVER) + strcat(flags, "DPSESSION_MULTICASTSERVER,"); + if (dwFlags & DPSESSION_CLIENTSERVER) + strcat(flags, "DPSESSION_CLIENTSERVER,"); + + if (dwFlags & DPSESSION_DIRECTPLAYPROTOCOL) + strcat(flags, "DPSESSION_DIRECTPLAYPROTOCOL,"); + if (dwFlags & DPSESSION_NOPRESERVEORDER) + strcat(flags, "DPSESSION_NOPRESERVEORDER,"); + if (dwFlags & DPSESSION_OPTIMIZELATENCY) + strcat(flags, "DPSESSION_OPTIMIZELATENCY,"); + + } + + /* DPLCONNECTION */ + + if (flagType & FLAGS_DPLCONNECTION) + { + if (dwFlags & DPLCONNECTION_CREATESESSION) + strcat(flags, "DPLCONNECTION_CREATESESSION,"); + if (dwFlags & DPLCONNECTION_JOINSESSION) + strcat(flags, "DPLCONNECTION_JOINSESSION,"); + } + + /* EnumSessionsCallback2 */ + + if (flagType & FLAGS_DPESC) + { + if (dwFlags & DPESC_TIMEDOUT) + strcat(flags, "DPESC_TIMEDOUT,"); + } + + /* GetCaps, + GetPlayerCaps */ + + if (flagType & FLAGS_DPCAPS) + { + if (dwFlags & DPCAPS_ISHOST) + strcat(flags, "DPCAPS_ISHOST,"); + if (dwFlags & DPCAPS_GROUPOPTIMIZED) + strcat(flags, "DPCAPS_GROUPOPTIMIZED,"); + if (dwFlags & DPCAPS_KEEPALIVEOPTIMIZED) + strcat(flags, "DPCAPS_KEEPALIVEOPTIMIZED,"); + if (dwFlags & DPCAPS_GUARANTEEDOPTIMIZED) + strcat(flags, "DPCAPS_GUARANTEEDOPTIMIZED,"); + if (dwFlags & DPCAPS_GUARANTEEDSUPPORTED) + strcat(flags, "DPCAPS_GUARANTEEDSUPPORTED,"); + if (dwFlags & DPCAPS_SIGNINGSUPPORTED) + strcat(flags, "DPCAPS_SIGNINGSUPPORTED,"); + if (dwFlags & DPCAPS_ENCRYPTIONSUPPORTED) + strcat(flags, "DPCAPS_ENCRYPTIONSUPPORTED,"); + if (dwFlags & DPCAPS_ASYNCCANCELSUPPORTED) + strcat(flags, "DPCAPS_ASYNCCANCELSUPPORTED,"); + if (dwFlags & DPCAPS_ASYNCCANCELALLSUPPORTED) + strcat(flags, "DPCAPS_ASYNCCANCELALLSUPPORTED,"); + if (dwFlags & DPCAPS_SENDTIMEOUTSUPPORTED) + strcat(flags, "DPCAPS_SENDTIMEOUTSUPPORTED,"); + if (dwFlags & DPCAPS_SENDPRIORITYSUPPORTED) + strcat(flags, "DPCAPS_SENDPRIORITYSUPPORTED,"); + if (dwFlags & DPCAPS_ASYNCSUPPORTED) + strcat(flags, "DPCAPS_ASYNCSUPPORTED,"); + + if (dwFlags & DPPLAYERCAPS_LOCAL) + strcat(flags, "DPPLAYERCAPS_LOCAL,"); + } + + if ((strlen(flags) == 0) && (dwFlags != 0)) + strcpy(flags, "UNKNOWN"); + else + flags[strlen(flags)-1] = '\0'; + + return flags; +} + +static void init_TCPIP_provider( LPDIRECTPLAY4 pDP, + LPCSTR strIPAddressString, + WORD port ) +{ + + DPCOMPOUNDADDRESSELEMENT addressElements[3]; + LPVOID pAddress = NULL; + DWORD dwAddressSize = 0; + LPDIRECTPLAYLOBBY3 pDPL; + HRESULT hr; + + CoCreateInstance( &CLSID_DirectPlayLobby, NULL, CLSCTX_ALL, + &IID_IDirectPlayLobby3A, (LPVOID*) &pDPL ); + + /* Service provider */ + addressElements[0].guidDataType = DPAID_ServiceProvider; + addressElements[0].dwDataSize = sizeof(GUID); + addressElements[0].lpData = (LPVOID) &DPSPGUID_TCPIP; + + /* IP address string */ + addressElements[1].guidDataType = DPAID_INet; + addressElements[1].dwDataSize = lstrlen(strIPAddressString) + 1; + addressElements[1].lpData = (LPVOID) strIPAddressString; + + /* Optional Port number */ + if( port > 0 ) + { + addressElements[2].guidDataType = DPAID_INetPort; + addressElements[2].dwDataSize = sizeof(WORD); + addressElements[2].lpData = &port; + } + + + hr = IDirectPlayLobby_CreateCompoundAddress( pDPL, addressElements, 2, + NULL, &dwAddressSize ); + checkHR( DPERR_BUFFERTOOSMALL, hr ); + + if( hr == DPERR_BUFFERTOOSMALL ) + { + pAddress = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwAddressSize ); + hr = IDirectPlayLobby_CreateCompoundAddress( pDPL, addressElements, 2, + pAddress, &dwAddressSize ); + checkHR( DP_OK, hr ); + } + + hr = IDirectPlayX_InitializeConnection( pDP, pAddress, 0 ); + todo_wine checkHR( DP_OK, hr ); + +} + + +/* DirectPlayCreate */ + +static void test_DirectPlayCreate(void) +{ + + LPDIRECTPLAY pDP; + HRESULT hr; + + /* TODO: Check how it behaves with pUnk!=NULL */ + + /* pDP==NULL */ + hr = DirectPlayCreate( NULL, NULL, NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = DirectPlayCreate( (LPGUID) &GUID_NULL, NULL, NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = DirectPlayCreate( (LPGUID) &DPSPGUID_TCPIP, NULL, NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + + /* pUnk==NULL, pDP!=NULL */ + hr = DirectPlayCreate( NULL, &pDP, NULL ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = DirectPlayCreate( (LPGUID) &GUID_NULL, &pDP, NULL ); + checkHR( DP_OK, hr ); + if ( hr == DP_OK ) + IDirectPlayX_Release( pDP ); + hr = DirectPlayCreate( (LPGUID) &DPSPGUID_TCPIP, &pDP, NULL ); + todo_wine checkHR( DP_OK, hr ); + if ( hr == DP_OK ) + IDirectPlayX_Release( pDP ); + +} + +/* EnumConnections */ + +static BOOL FAR PASCAL EnumAddress_cb2( REFGUID guidDataType, + DWORD dwDataSize, + LPCVOID lpData, + LPVOID lpContext ) +{ + lpCallbackData callbackData = (lpCallbackData) lpContext; + + static REFGUID types[] = { &DPAID_TotalSize, + &DPAID_ServiceProvider, + &GUID_NULL }; + static DWORD sizes[] = { 4, 16, 0 }; + static REFGUID sps[] = { &DPSPGUID_SERIAL, &DPSPGUID_MODEM, + &DPSPGUID_IPX, &DPSPGUID_TCPIP }; + + + checkGuid( types[ callbackData->dwCounter2 ], guidDataType ); + check( sizes[ callbackData->dwCounter2 ], dwDataSize ); + + if ( IsEqualGUID( types[0], guidDataType ) ) + { + todo_wine check( 80, *((LPDWORD) lpData) ); + } + else if ( IsEqualGUID( types[1], guidDataType ) ) + { + todo_wine checkGuid( sps[ callbackData->dwCounter1 ], (LPGUID) lpData ); + } + + callbackData->dwCounter2++; + + return TRUE; +} + +static BOOL CALLBACK EnumConnections_cb( LPCGUID lpguidSP, + LPVOID lpConnection, + DWORD dwConnectionSize, + LPCDPNAME lpName, + DWORD dwFlags, + LPVOID lpContext ) +{ + + lpCallbackData callbackData = (lpCallbackData) lpContext; + LPDIRECTPLAYLOBBY pDPL; + + + if (!callbackData->dwFlags) + { + callbackData->dwFlags = DPCONNECTION_DIRECTPLAY; + } + + checkFlags( callbackData->dwFlags, dwFlags, FLAGS_DPCONNECTION ); + + /* Get info from lpConnection */ + CoCreateInstance( &CLSID_DirectPlayLobby, NULL, CLSCTX_ALL, + &IID_IDirectPlayLobby3A, (LPVOID*) &pDPL ); + + callbackData->dwCounter2 = 0; + IDirectPlayLobby_EnumAddress( pDPL, EnumAddress_cb2, + (LPCVOID) lpConnection, + dwConnectionSize, + (LPVOID) callbackData ); + todo_wine check( 3, callbackData->dwCounter2 ); + + callbackData->dwCounter1++; + + return TRUE; +} + +static void test_EnumConnections(void) +{ + + LPDIRECTPLAY4 pDP; + CallbackData callbackData; + HRESULT hr; + + + CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = 0; + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb, + (LPVOID) &callbackData, + callbackData.dwFlags ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = 0; + hr = IDirectPlayX_EnumConnections( pDP, NULL, EnumConnections_cb, + (LPVOID) &callbackData, + callbackData.dwFlags ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = 0; + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, NULL, + (LPVOID) &callbackData, + callbackData.dwFlags ); + checkHR( DPERR_INVALIDPARAMS, hr ); + check( 0, callbackData.dwCounter1 ); + + + /* Flag tests */ + callbackData.dwCounter1 = 0; + callbackData.dwFlags = DPCONNECTION_DIRECTPLAY; + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb, + (LPVOID) &callbackData, + callbackData.dwFlags ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = DPCONNECTION_DIRECTPLAYLOBBY; + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb, + (LPVOID) &callbackData, + callbackData.dwFlags ); + checkHR( DP_OK, hr ); + check( 0, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = ( DPCONNECTION_DIRECTPLAY | + DPCONNECTION_DIRECTPLAYLOBBY ); + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb, + (LPVOID) &callbackData, + callbackData.dwFlags ); + checkHR( DP_OK, hr ); + check( 4, callbackData.dwCounter1 ); + + callbackData.dwCounter1 = 0; + callbackData.dwFlags = ~( DPCONNECTION_DIRECTPLAY | + DPCONNECTION_DIRECTPLAYLOBBY ); + hr = IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb, + (LPVOID) &callbackData, + callbackData.dwFlags ); + checkHR( DPERR_INVALIDFLAGS, hr ); + check( 0, callbackData.dwCounter1 ); + + + IDirectPlayX_Release( pDP ); +} + +/* InitializeConnection */ + +static BOOL CALLBACK EnumConnections_cb2( LPCGUID lpguidSP, + LPVOID lpConnection, + DWORD dwConnectionSize, + LPCDPNAME lpName, + DWORD dwFlags, + LPVOID lpContext ) +{ + LPDIRECTPLAY4 pDP = (LPDIRECTPLAY4) lpContext; + HRESULT hr; + + /* Incorrect parameters */ + hr = IDirectPlayX_InitializeConnection( pDP, NULL, 1 ); + checkHR( DPERR_INVALIDPARAMS, hr ); + hr = IDirectPlayX_InitializeConnection( pDP, lpConnection, 1 ); + checkHR( DPERR_INVALIDFLAGS, hr ); + + /* Normal operation. + We're only interested in ensuring that the TCP/IP provider works */ + + if( IsEqualGUID(lpguidSP, &DPSPGUID_TCPIP) ) + { + hr = IDirectPlayX_InitializeConnection( pDP, lpConnection, 0 ); + todo_wine checkHR( DP_OK, hr ); + hr = IDirectPlayX_InitializeConnection( pDP, lpConnection, 0 ); + todo_wine checkHR( DPERR_ALREADYINITIALIZED, hr ); + } + + return TRUE; +} + +static void test_InitializeConnection(void) +{ + + LPDIRECTPLAY4 pDP; + + CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + + IDirectPlayX_EnumConnections( pDP, &appGuid, EnumConnections_cb2, + (LPVOID) pDP, 0 ); + + IDirectPlayX_Release( pDP ); +} + +/* GetCaps */ + +static void test_GetCaps(void) +{ + + LPDIRECTPLAY4 pDP; + DPCAPS dpcaps; + DWORD dwFlags; + HRESULT hr; + + + CoCreateInstance( &CLSID_DirectPlay, NULL, CLSCTX_ALL, + &IID_IDirectPlay4A, (LPVOID*) &pDP ); + ZeroMemory( &dpcaps, sizeof(DPCAPS) ); + + /* Service provider not ininitialized */ + hr = IDirectPlayX_GetCaps( pDP, &dpcaps, 0 ); + checkHR( DPERR_UNINITIALIZED, hr ); + + init_TCPIP_provider( pDP, "127.0.0.1", 0 ); + + /* dpcaps not ininitialized */ + hr = IDirectPlayX_GetCaps( pDP, &dpcaps, 0 ); + todo_wine checkHR( DPERR_INVALIDPARAMS, hr ); + + dpcaps.dwSize = sizeof(DPCAPS); + + for (dwFlags=0; + dwFlags<=DPGETCAPS_GUARANTEED; + dwFlags+=DPGETCAPS_GUARANTEED) + { + + hr = IDirectPlayX_GetCaps( pDP, &dpcaps, dwFlags ); + todo_wine checkHR( DP_OK, hr ); + + + if ( hr == DP_OK ) + { + check( sizeof(DPCAPS), dpcaps.dwSize ); + check( DPCAPS_ASYNCSUPPORTED | + DPCAPS_GUARANTEEDOPTIMIZED | + DPCAPS_GUARANTEEDSUPPORTED, + dpcaps.dwFlags ); + check( 0, dpcaps.dwMaxQueueSize ); + check( 0, dpcaps.dwHundredBaud ); + check( 500, dpcaps.dwLatency ); + check( 65536, dpcaps.dwMaxLocalPlayers ); + check( 20, dpcaps.dwHeaderLength ); + check( 5000, dpcaps.dwTimeout ); + + switch (dwFlags) + { + case 0: + check( 65479, dpcaps.dwMaxBufferSize ); + check( 65536, dpcaps.dwMaxPlayers ); + break; + case DPGETCAPS_GUARANTEED: + check( 1048547, dpcaps.dwMaxBufferSize ); + check( 64, dpcaps.dwMaxPlayers ); + break; + default: break; + } + } + } + + IDirectPlayX_Release( pDP ); +} + + +START_TEST(dplayx) +{ + CoInitialize( NULL ); + + test_DirectPlayCreate(); + test_EnumConnections(); + test_InitializeConnection(); + + test_GetCaps(); + + CoUninitialize(); +} diff --git a/dlls/dpnet/Makefile.in b/dlls/dpnet/Makefile.in index 044eabafddb..8d6b31959c1 100644 --- a/dlls/dpnet/Makefile.in +++ b/dlls/dpnet/Makefile.in @@ -13,7 +13,8 @@ C_SRCS = \ lobbiedapp.c \ peer.c \ regsvr.c \ - server.c + server.c \ + threadpool.c RC_SRCS = version.rc diff --git a/dlls/dpnet/dpnet_main.c b/dlls/dpnet/dpnet_main.c index 1a2a90c78ce..3c8e2c515eb 100644 --- a/dlls/dpnet/dpnet_main.c +++ b/dlls/dpnet/dpnet_main.c @@ -115,6 +115,7 @@ static IClassFactoryImpl DPNET_CFS[] = { { &DICF_Vtbl, 1, &CLSID_DirectPlay8Peer, DPNET_CreateDirectPlay8Peer }, { &DICF_Vtbl, 1, &CLSID_DirectPlay8Address, DPNET_CreateDirectPlay8Address }, { &DICF_Vtbl, 1, &CLSID_DirectPlay8LobbiedApplication, (void *)DPNET_CreateDirectPlay8LobbiedApp }, + { &DICF_Vtbl, 1, &CLSID_DirectPlay8ThreadPool, DPNET_CreateDirectPlay8ThreadPool}, { NULL, 0, NULL, NULL } }; diff --git a/dlls/dpnet/dpnet_private.h b/dlls/dpnet/dpnet_private.h index 40cd671239d..deaee60eeab 100644 --- a/dlls/dpnet/dpnet_private.h +++ b/dlls/dpnet/dpnet_private.h @@ -35,6 +35,7 @@ typedef struct IDirectPlay8ClientImpl IDirectPlay8ClientImpl; typedef struct IDirectPlay8AddressImpl IDirectPlay8AddressImpl; typedef struct IDirectPlay8LobbiedApplicationImpl IDirectPlay8LobbiedApplicationImpl; +typedef struct IDirectPlay8ThreadPoolImpl IDirectPlay8ThreadPoolImpl; /* ------------------ */ /* IDirectPlay8Client */ @@ -79,6 +80,16 @@ struct IDirectPlay8LobbiedApplicationImpl /* IDirectPlay8LobbiedApplication fields */ }; +/***************************************************************************** + * IDirectPlay8ThreadPool implementation structure + */ +struct IDirectPlay8ThreadPoolImpl +{ + /* IUnknown fields */ + const IDirectPlay8ThreadPoolVtbl *lpVtbl; + LONG ref; +}; + /** * factories */ @@ -87,6 +98,7 @@ extern HRESULT DPNET_CreateDirectPlay8Server(LPCLASSFACTORY iface, LPUNKNOWN pun extern HRESULT DPNET_CreateDirectPlay8Peer(LPCLASSFACTORY iface, LPUNKNOWN punkOuter, REFIID riid, LPVOID *ppobj); extern HRESULT DPNET_CreateDirectPlay8Address(LPCLASSFACTORY iface, LPUNKNOWN punkOuter, REFIID riid, LPVOID *ppobj); extern HRESULT DPNET_CreateDirectPlay8LobbiedApp(LPCLASSFACTORY iface, LPUNKNOWN punkOuter, REFIID riid, LPVOID *ppobj); +extern HRESULT DPNET_CreateDirectPlay8ThreadPool(LPCLASSFACTORY iface, LPUNKNOWN punkOuter, REFIID riid, LPVOID *ppobj); /** * debug diff --git a/dlls/dpnet/threadpool.c b/dlls/dpnet/threadpool.c new file mode 100644 index 00000000000..1c530501f61 --- /dev/null +++ b/dlls/dpnet/threadpool.c @@ -0,0 +1,143 @@ +/* + * DirectPlay8 ThreadPool + * + * Copyright 2004 Raphael Junqueira + * Copyright 2008 Alexander N. Sørnes + * + * 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 + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "objbase.h" +#include "wine/debug.h" + +#include "dplay8.h" +#include "dpnet_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dpnet); + +/* IUnknown interface follows */ + +static HRESULT WINAPI IDirectPlay8ThreadPoolImpl_QueryInterface(PDIRECTPLAY8THREADPOOL iface, REFIID riid, LPVOID *ppobj) +{ + IDirectPlay8ThreadPoolImpl *This = (IDirectPlay8ThreadPoolImpl*)iface; + + if(IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IDirectPlay8ThreadPool)) + { + IUnknown_AddRef(iface); + *ppobj = This; + return DPN_OK; + } + + WARN("(%p)->(%s,%p): not found\n", This, debugstr_guid(riid), ppobj); + return E_NOINTERFACE; +} + +static ULONG WINAPI IDirectPlay8ThreadPoolImpl_AddRef(PDIRECTPLAY8THREADPOOL iface) +{ + IDirectPlay8ThreadPoolImpl* This = (IDirectPlay8ThreadPoolImpl*)iface; + ULONG RefCount = InterlockedIncrement(&This->ref); + + return RefCount; +} + +static ULONG WINAPI IDirectPlay8ThreadPoolImpl_Release(PDIRECTPLAY8THREADPOOL iface) +{ + IDirectPlay8ThreadPoolImpl* This = (IDirectPlay8ThreadPoolImpl*)This; + ULONG RefCount = InterlockedDecrement(&This->ref); + + if(!RefCount) + HeapFree(GetProcessHeap(), 0, This); + + return RefCount; +} + +/* IDirectPlay8ThreadPool interface follows */ +static HRESULT WINAPI IDirectPlay8ThreadPoolImpl_Initialize(PDIRECTPLAY8THREADPOOL iface, PVOID CONST pvUserContext, CONST PFNDPNMESSAGEHANDLER pfn, CONST DWORD dwFlags) +{ + FIXME("(%p)->(%p,%p,%x): stub\n", iface, pvUserContext, pfn, dwFlags); + return DPN_OK; +} + +static HRESULT WINAPI IDirectPlay8ThreadPoolImpl_Close(PDIRECTPLAY8THREADPOOL iface, CONST DWORD dwFlags) +{ + return DPN_OK; +} + +static HRESULT WINAPI IDirectPlay8ThreadPoolImpl_GetThreadCount(PDIRECTPLAY8THREADPOOL iface, CONST DWORD dwProcessorNum, DWORD* CONST pdwNumThreads, CONST DWORD dwFlags) +{ + FIXME("(%p)->(%x,%p,%x): stub\n", iface, dwProcessorNum, pdwNumThreads, dwFlags); + *pdwNumThreads = 0; + return DPN_OK; +} + +static HRESULT WINAPI IDirectPlay8ThreadPoolImpl_SetThreadCount(PDIRECTPLAY8THREADPOOL iface, CONST DWORD dwProcessorNum, CONST DWORD dwNumThreads, CONST DWORD dwFlags) +{ + FIXME("(%p)->(%x,%x,%x): stub\n", iface, dwProcessorNum, dwNumThreads, dwFlags); + return DPN_OK; +} + +static HRESULT WINAPI IDirectPlay8ThreadPoolImpl_DoWork(PDIRECTPLAY8THREADPOOL iface, CONST DWORD dwAllowedTimeSlice, CONST DWORD dwFlags) +{ + static BOOL Run = FALSE; + + if(!Run) + FIXME("(%p)->(%x,%x): stub\n", iface, dwAllowedTimeSlice, dwFlags); + + Run = TRUE; + + return DPN_OK; +} + +static const IDirectPlay8ThreadPoolVtbl DirectPlay8ThreadPool_Vtbl = +{ + IDirectPlay8ThreadPoolImpl_QueryInterface, + IDirectPlay8ThreadPoolImpl_AddRef, + IDirectPlay8ThreadPoolImpl_Release, + IDirectPlay8ThreadPoolImpl_Initialize, + IDirectPlay8ThreadPoolImpl_Close, + IDirectPlay8ThreadPoolImpl_GetThreadCount, + IDirectPlay8ThreadPoolImpl_SetThreadCount, + IDirectPlay8ThreadPoolImpl_DoWork +}; + +HRESULT DPNET_CreateDirectPlay8ThreadPool(LPCLASSFACTORY iface, LPUNKNOWN punkOuter, REFIID riid, LPVOID *ppobj) +{ + IDirectPlay8ThreadPoolImpl* Client; + + Client = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectPlay8ThreadPoolImpl)); + + if(Client == NULL) + { + *ppobj = NULL; + WARN("Not enough memory\n"); + return E_OUTOFMEMORY; + } + + Client->lpVtbl = &DirectPlay8ThreadPool_Vtbl; + Client->ref = 0; + + return IDirectPlay8ThreadPoolImpl_QueryInterface((PDIRECTPLAY8THREADPOOL)Client, riid, ppobj); +} diff --git a/dlls/dswave/dswave_main.c b/dlls/dswave/dswave_main.c index 2a951abf5bb..a94c504f81d 100644 --- a/dlls/dswave/dswave_main.c +++ b/dlls/dswave/dswave_main.c @@ -477,7 +477,8 @@ const char *debugstr_dmreturn (DWORD code) { /* generic flag-dumping function */ const char* debugstr_flags (DWORD flags, const flag_info* names, size_t num_names){ char buffer[128] = "", *ptr = &buffer[0]; - unsigned int i, size = sizeof(buffer); + unsigned int i; + int size = sizeof(buffer); for (i=0; i < num_names; i++) { diff --git a/dlls/gdi32/bitblt.c b/dlls/gdi32/bitblt.c index f446e260b04..cff45be3eb8 100644 --- a/dlls/gdi32/bitblt.c +++ b/dlls/gdi32/bitblt.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "config.h" + #include #include diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 91e41e7ef39..013cd2abae2 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -3254,11 +3254,6 @@ BOOL WINAPI FontIsLinked(HDC hdc) return ret; } -/************************************************************* - * GdiRealizationInfo (GDI32.@) - * - * Returns a structure that contains some font information. - */ typedef struct { DWORD flags; /* 1 for bitmap fonts, 3 for scalable fonts */ @@ -3267,6 +3262,11 @@ typedef struct in which the face was first rendered. */ } realization_info_t; +/************************************************************* + * GdiRealizationInfo (GDI32.@) + * + * Returns a structure that contains some font information. + */ BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info) { UINT otm_size; diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c index 9e8f408764f..7065cd5af39 100644 --- a/dlls/gdi32/tests/font.c +++ b/dlls/gdi32/tests/font.c @@ -533,7 +533,7 @@ static void test_outline_font(void) 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(near_match(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)); @@ -543,7 +543,7 @@ static void test_outline_font(void) 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(near_match(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); @@ -2363,7 +2363,13 @@ static void test_GetTextFace(void) /* 'W' case. */ memcpy(fW.lfFaceName, faceW, sizeof faceW); + SetLastError(0xdeadbeef); f = CreateFontIndirectW(&fW); + if (!f && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + win_skip("CreateFontIndirectW is not implemented\n"); + return; + } ok(f != NULL, "CreateFontIndirectW failed\n"); dc = GetDC(NULL); diff --git a/dlls/gdiplus/customlinecap.c b/dlls/gdiplus/customlinecap.c index e8e18bc3806..48a20dfbc10 100644 --- a/dlls/gdiplus/customlinecap.c +++ b/dlls/gdiplus/customlinecap.c @@ -100,6 +100,8 @@ GpStatus WINGDIPAPI GdipCreateCustomLineCap(GpPath* fillPath, GpPath* strokePath (*customCap)->inset = baseInset; (*customCap)->cap = baseCap; + (*customCap)->join = LineJoinMiter; + (*customCap)->scale = 1.0; return Ok; } @@ -116,6 +118,28 @@ GpStatus WINGDIPAPI GdipDeleteCustomLineCap(GpCustomLineCap *customCap) return Ok; } +GpStatus WINGDIPAPI GdipGetCustomLineCapStrokeJoin(GpCustomLineCap* customCap, + GpLineJoin* lineJoin) +{ + if(!customCap || !lineJoin) + return InvalidParameter; + + *lineJoin = customCap->join; + + return Ok; +} + +GpStatus WINGDIPAPI GdipGetCustomLineCapWidthScale(GpCustomLineCap* custom, + REAL* widthScale) +{ + if(!custom || !widthScale) + return InvalidParameter; + + *widthScale = custom->scale; + + return Ok; +} + GpStatus WINGDIPAPI GdipSetCustomLineCapStrokeCaps(GpCustomLineCap* custom, GpLineCap start, GpLineCap end) { @@ -144,12 +168,12 @@ GpStatus WINGDIPAPI GdipSetCustomLineCapBaseCap(GpCustomLineCap* custom, GpStatus WINGDIPAPI GdipGetCustomLineCapBaseInset(GpCustomLineCap* custom, REAL* inset) { - static int calls; + if(!custom || !inset) + return InvalidParameter; - if(!(calls++)) - FIXME("not implemented\n"); + *inset = custom->inset; - return NotImplemented; + return Ok; } GpStatus WINGDIPAPI GdipSetCustomLineCapBaseInset(GpCustomLineCap* custom, @@ -163,15 +187,16 @@ GpStatus WINGDIPAPI GdipSetCustomLineCapBaseInset(GpCustomLineCap* custom, return NotImplemented; } +/*FIXME: LineJoin completely ignored now */ GpStatus WINGDIPAPI GdipSetCustomLineCapStrokeJoin(GpCustomLineCap* custom, GpLineJoin join) { - static int calls; + if(!custom) + return InvalidParameter; - if(!(calls++)) - FIXME("not implemented\n"); + custom->join = join; - return NotImplemented; + return Ok; } GpStatus WINGDIPAPI GdipSetCustomLineCapWidthScale(GpCustomLineCap* custom, diff --git a/dlls/gdiplus/font.c b/dlls/gdiplus/font.c index 4e756e5313e..70f7bb04b3e 100644 --- a/dlls/gdiplus/font.c +++ b/dlls/gdiplus/font.c @@ -157,6 +157,9 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily, return Ok; } +/******************************************************************************* + * GdipCreateFontFromLogfontW [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc, GDIPCONST LOGFONTW *logfont, GpFont **font) { @@ -192,6 +195,9 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontW(HDC hdc, return Ok; } +/******************************************************************************* + * GdipCreateFontFromLogfontA [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipCreateFontFromLogfontA(HDC hdc, GDIPCONST LOGFONTA *lfa, GpFont **font) { @@ -210,6 +216,9 @@ GpStatus WINGDIPAPI GdipCreateFontFromLogfontA(HDC hdc, return Ok; } +/******************************************************************************* + * GdipDeleteFont [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipDeleteFont(GpFont* font) { if(!font) @@ -220,6 +229,9 @@ GpStatus WINGDIPAPI GdipDeleteFont(GpFont* font) return Ok; } +/******************************************************************************* + * GdipCreateFontFromDC [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipCreateFontFromDC(HDC hdc, GpFont **font) { HFONT hfont; @@ -283,10 +295,13 @@ GpStatus WINGDIPAPI GdipGetFontUnit(GpFont *font, Unit *unit) return Ok; } -/* FIXME: use graphics */ +/******************************************************************************* + * GdipGetLogFontW [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, LOGFONTW *lfw) { + /* FIXME: use graphics */ if(!font || !graphics || !lfw) return InvalidParameter; @@ -295,6 +310,9 @@ GpStatus WINGDIPAPI GdipGetLogFontW(GpFont *font, GpGraphics *graphics, return Ok; } +/******************************************************************************* + * GdipCloneFont [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipCloneFont(GpFont *font, GpFont **cloneFont) { if(!font || !cloneFont) @@ -645,6 +663,9 @@ GpStatus WINGDIPAPI GdipGetGenericFontFamilySansSerif(GpFontFamily **nativeFamil return GdipCreateFontFamilyFromName(MSSansSerif, NULL, nativeFamily); } +/***************************************************************************** + * GdipGetGenericFontFamilySansSerif [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipNewPrivateFontCollection(GpFontCollection** fontCollection) { FIXME("stub %p\n", fontCollection); @@ -655,6 +676,9 @@ GpStatus WINGDIPAPI GdipNewPrivateFontCollection(GpFontCollection** fontCollecti return NotImplemented; } +/***************************************************************************** + * GdipDeletePrivateFontCollection [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipDeletePrivateFontCollection(GpFontCollection **fontCollection) { FIXME("stub %p\n", fontCollection); @@ -665,6 +689,9 @@ GpStatus WINGDIPAPI GdipDeletePrivateFontCollection(GpFontCollection **fontColle return NotImplemented; } +/***************************************************************************** + * GdipPrivateAddFontFile [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipPrivateAddFontFile(GpFontCollection* fontCollection, GDIPCONST WCHAR* filename) { @@ -676,6 +703,9 @@ GpStatus WINGDIPAPI GdipPrivateAddFontFile(GpFontCollection* fontCollection, return NotImplemented; } +/***************************************************************************** + * GdipGetFontCollectionFamilyCount [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyCount( GpFontCollection* fontCollection, INT* numFound) { @@ -687,6 +717,9 @@ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyCount( return NotImplemented; } +/***************************************************************************** + * GdipGetFontCollectionFamilyList [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyList( GpFontCollection* fontCollection, INT numSought, GpFontFamily* gpfamilies[], INT* numFound) diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec index b55b4b1dc69..5b046a1f4e7 100644 --- a/dlls/gdiplus/gdiplus.spec +++ b/dlls/gdiplus/gdiplus.spec @@ -252,9 +252,9 @@ @ stdcall GdipGetCustomLineCapBaseCap(ptr ptr) @ stdcall GdipGetCustomLineCapBaseInset(ptr ptr) @ stub GdipGetCustomLineCapStrokeCaps -@ stub GdipGetCustomLineCapStrokeJoin +@ stdcall GdipGetCustomLineCapStrokeJoin(ptr ptr) @ stub GdipGetCustomLineCapType -@ stub GdipGetCustomLineCapWidthScale +@ stdcall GdipGetCustomLineCapWidthScale(ptr ptr) @ stdcall GdipGetDC(ptr ptr) @ stdcall GdipGetDpiX(ptr ptr) @ stdcall GdipGetDpiY(ptr ptr) @@ -352,8 +352,8 @@ @ stdcall GdipGetPenColor(ptr ptr) @ stub GdipGetPenCompoundArray @ stub GdipGetPenCompoundCount -@ stub GdipGetPenCustomEndCap -@ stub GdipGetPenCustomStartCap +@ stdcall GdipGetPenCustomEndCap(ptr ptr) +@ stdcall GdipGetPenCustomStartCap(ptr ptr) @ stdcall GdipGetPenDashArray(ptr ptr long) @ stdcall GdipGetPenDashCap197819(ptr ptr) @ stdcall GdipGetPenDashCount(ptr ptr) @@ -363,7 +363,7 @@ @ stub GdipGetPenFillType @ stdcall GdipGetPenLineJoin(ptr ptr) @ stdcall GdipGetPenMiterLimit(ptr ptr) -@ stub GdipGetPenMode +@ stdcall GdipGetPenMode(ptr ptr) @ stdcall GdipGetPenStartCap(ptr ptr) @ stub GdipGetPenTransform @ stdcall GdipGetPenUnit(ptr ptr) @@ -387,13 +387,13 @@ @ stdcall GdipGetSmoothingMode(ptr ptr) @ stdcall GdipGetSolidFillColor(ptr ptr) @ stdcall GdipGetStringFormatAlign(ptr ptr) -@ stub GdipGetStringFormatDigitSubstitution +@ stdcall GdipGetStringFormatDigitSubstitution(ptr ptr ptr) @ stdcall GdipGetStringFormatFlags(ptr ptr) @ stdcall GdipGetStringFormatHotkeyPrefix(ptr ptr) @ stdcall GdipGetStringFormatLineAlign(ptr ptr) @ stdcall GdipGetStringFormatMeasurableCharacterRangeCount(ptr ptr) -@ stub GdipGetStringFormatTabStopCount -@ stub GdipGetStringFormatTabStops +@ stdcall GdipGetStringFormatTabStopCount(ptr ptr) +@ stdcall GdipGetStringFormatTabStops(ptr long ptr ptr) @ stdcall GdipGetStringFormatTrimming(ptr ptr) @ stub GdipGetTextContrast @ stdcall GdipGetTextRenderingHint(ptr ptr) @@ -586,12 +586,12 @@ @ stdcall GdipSetSmoothingMode(ptr long) @ stdcall GdipSetSolidFillColor(ptr ptr) @ stdcall GdipSetStringFormatAlign(ptr long) -@ stub GdipSetStringFormatDigitSubstitution +@ stdcall GdipSetStringFormatDigitSubstitution(ptr long long) @ stdcall GdipSetStringFormatFlags(ptr long) @ stdcall GdipSetStringFormatHotkeyPrefix(ptr long) @ stdcall GdipSetStringFormatLineAlign(ptr long) @ stdcall GdipSetStringFormatMeasurableCharacterRanges(ptr long ptr) -@ stub GdipSetStringFormatTabStops +@ stdcall GdipSetStringFormatTabStops(ptr long long ptr) @ stdcall GdipSetStringFormatTrimming(ptr long) @ stub GdipSetTextContrast @ stdcall GdipSetTextRenderingHint(ptr long) @@ -601,7 +601,7 @@ @ stdcall GdipShearMatrix(ptr long long long) @ stdcall GdipStartPathFigure(ptr) @ stdcall GdipStringFormatGetGenericDefault(ptr) -@ stub GdipStringFormatGetGenericTypographic +@ stdcall GdipStringFormatGetGenericTypographic(ptr) @ stub GdipTestControl @ stdcall GdipTransformMatrixPoints(ptr ptr long) @ stdcall GdipTransformMatrixPointsI(ptr ptr long) diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 620f82269bc..8fe8862e50d 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -72,6 +72,7 @@ struct GpPen{ INT numdashes; REAL offset; /* dash offset */ GpBrush *brush; + GpPenAlignment align; }; struct GpGraphics{ @@ -149,6 +150,8 @@ struct GpCustomLineCap{ BOOL fill; /* TRUE for fill, FALSE for stroke */ GpLineCap cap; /* as far as I can tell, this value is ignored */ REAL inset; /* how much to adjust the end of the line */ + GpLineJoin join; + REAL scale; }; struct GpImage{ @@ -186,10 +189,15 @@ struct GpFont{ struct GpStringFormat{ INT attr; LANGID lang; + LANGID digitlang; StringAlignment align; StringTrimming trimming; HotkeyPrefix hkprefix; StringAlignment vertalign; + StringDigitSubstitute digitsub; + INT tabcount; + REAL firsttab; + REAL *tabs; }; struct GpFontCollection{ diff --git a/dlls/gdiplus/image.c b/dlls/gdiplus/image.c index 25a5c4deaa5..197665d0299 100644 --- a/dlls/gdiplus/image.c +++ b/dlls/gdiplus/image.c @@ -1003,6 +1003,9 @@ static encode_image_func *const encode_image_funcs[NUM_ENCODERS_SUPPORTED] = { encode_image_BMP, }; +/***************************************************************************** + * GdipSaveImageToStream [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream, GDIPCONST CLSID* clsid, GDIPCONST EncoderParameters* params) { @@ -1085,6 +1088,9 @@ GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream* stream, return stat; } +/***************************************************************************** + * GdipSetImagePalette [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipSetImagePalette(GpImage *image, GDIPCONST ColorPalette *palette) { @@ -1131,6 +1137,9 @@ static const ImageCodecInfo codecs[NUM_ENCODERS_SUPPORTED] = }, }; +/***************************************************************************** + * GdipGetImageEncodersSize [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipGetImageEncodersSize(UINT *numEncoders, UINT *size) { if (!numEncoders || !size) @@ -1142,6 +1151,9 @@ GpStatus WINGDIPAPI GdipGetImageEncodersSize(UINT *numEncoders, UINT *size) return Ok; } +/***************************************************************************** + * GdipGetImageEncoders [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipGetImageEncoders(UINT numEncoders, UINT size, ImageCodecInfo *encoders) { if (!encoders || @@ -1153,6 +1165,10 @@ GpStatus WINGDIPAPI GdipGetImageEncoders(UINT numEncoders, UINT size, ImageCodec return Ok; } + +/***************************************************************************** + * GdipCreateBitmapFromHBITMAP [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBitmap** bitmap) { BITMAP bm; @@ -1199,6 +1215,9 @@ GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBi return retval; } +/***************************************************************************** + * GdipSetEffectParameters [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipSetEffectParameters(CGpEffect *effect, const VOID *params, const UINT size) { @@ -1210,6 +1229,9 @@ GpStatus WINGDIPAPI GdipSetEffectParameters(CGpEffect *effect, return NotImplemented; } +/***************************************************************************** + * GdipGetImageFlags [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipGetImageFlags(GpImage *image, UINT *flags) { if(!image || !flags) diff --git a/dlls/gdiplus/pen.c b/dlls/gdiplus/pen.c index df2d040caa3..104d9de6485 100644 --- a/dlls/gdiplus/pen.c +++ b/dlls/gdiplus/pen.c @@ -116,6 +116,8 @@ GpStatus WINGDIPAPI GdipCreatePen2(GpBrush *brush, REAL width, GpUnit unit, gp_pen->miterlimit = 10.0; gp_pen->dash = DashStyleSolid; gp_pen->offset = 0.0; + gp_pen->customstart = NULL; + gp_pen->customend = NULL; if(!((gp_pen->unit == UnitWorld) || (gp_pen->unit == UnitPixel))) { FIXME("UnitWorld, UnitPixel only supported units\n"); @@ -163,6 +165,32 @@ GpStatus WINGDIPAPI GdipGetPenColor(GpPen *pen, ARGB *argb) return GdipGetSolidFillColor(((GpSolidFill*)pen->brush), argb); } +GpStatus WINGDIPAPI GdipGetPenCustomEndCap(GpPen *pen, GpCustomLineCap** customCap) +{ + if(!pen || !customCap) + return InvalidParameter; + + if(!pen->customend){ + *customCap = NULL; + return Ok; + } + + return GdipCloneCustomLineCap(pen->customend, customCap); +} + +GpStatus WINGDIPAPI GdipGetPenCustomStartCap(GpPen *pen, GpCustomLineCap** customCap) +{ + if(!pen || !customCap) + return InvalidParameter; + + if(!pen->customstart){ + *customCap = NULL; + return Ok; + } + + return GdipCloneCustomLineCap(pen->customstart, customCap); +} + GpStatus WINGDIPAPI GdipGetPenDashArray(GpPen *pen, REAL *dash, INT count) { if(!pen || !dash || count > pen->numdashes) @@ -237,6 +265,16 @@ GpStatus WINGDIPAPI GdipGetPenLineJoin(GpPen *pen, GpLineJoin *lineJoin) return Ok; } +GpStatus WINGDIPAPI GdipGetPenMode(GpPen *pen, GpPenAlignment *mode) +{ + if(!pen || !mode) + return InvalidParameter; + + *mode = pen->align; + + return Ok; +} + GpStatus WINGDIPAPI GdipGetPenMiterLimit(GpPen *pen, REAL *miterLimit) { if(!pen || !miterLimit) @@ -302,7 +340,8 @@ GpStatus WINGDIPAPI GdipSetPenCustomEndCap(GpPen *pen, GpCustomLineCap* customCa GpCustomLineCap * cap; GpStatus ret; - if(!pen || !customCap) return InvalidParameter; + /* native crashes on pen == NULL, customCap != NULL */ + if(!customCap) return InvalidParameter; if((ret = GdipCloneCustomLineCap(customCap, &cap)) == Ok){ GdipDeleteCustomLineCap(pen->customend); @@ -318,7 +357,8 @@ GpStatus WINGDIPAPI GdipSetPenCustomStartCap(GpPen *pen, GpCustomLineCap* custom GpCustomLineCap * cap; GpStatus ret; - if(!pen || !customCap) return InvalidParameter; + /* native crashes on pen == NULL, customCap != NULL */ + if(!customCap) return InvalidParameter; if((ret = GdipCloneCustomLineCap(customCap, &cap)) == Ok){ GdipDeleteCustomLineCap(pen->customstart); @@ -481,12 +521,11 @@ GpStatus WINGDIPAPI GdipSetPenWidth(GpPen *pen, REAL width) return Ok; } - -GpStatus WINGDIPAPI GdipSetPenMode(GpPen *pen, GpPenAlignment penAlignment) +GpStatus WINGDIPAPI GdipSetPenMode(GpPen *pen, GpPenAlignment mode) { if(!pen) return InvalidParameter; - FIXME("stub (%d)\n", penAlignment); + pen->align = mode; return Ok; } diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c index 6c52623f771..c4007b3ff38 100644 --- a/dlls/gdiplus/region.c +++ b/dlls/gdiplus/region.c @@ -142,6 +142,9 @@ static inline void delete_element(region_element* element) } } +/***************************************************************************** + * GdipCloneRegion [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipCloneRegion(GpRegion *region, GpRegion **clone) { FIXME("(%p %p): stub\n", region, clone); @@ -278,6 +281,9 @@ GpStatus WINGDIPAPI GdipGetRegionDataSize(GpRegion *region, UINT *needed) return Ok; } +/***************************************************************************** + * GdipGetRegionHRgn [GDIPLUS.@] + */ GpStatus WINGDIPAPI GdipGetRegionHRgn(GpRegion *region, GpGraphics *graphics, HRGN *hrgn) { FIXME("(%p, %p, %p): stub\n", region, graphics, hrgn); @@ -330,7 +336,7 @@ GpStatus WINGDIPAPI GdipSetInfinite(GpRegion *region) if (!region) return InvalidParameter; - TRACE("%p", region); + TRACE("%p\n", region); delete_element(®ion->node); stat = init_region(region, RegionDataInfiniteRect); diff --git a/dlls/gdiplus/stringformat.c b/dlls/gdiplus/stringformat.c index c9361dc504d..201201a866f 100644 --- a/dlls/gdiplus/stringformat.c +++ b/dlls/gdiplus/stringformat.c @@ -43,7 +43,13 @@ GpStatus WINGDIPAPI GdipCreateStringFormat(INT attr, LANGID lang, (*format)->attr = attr; (*format)->lang = lang; + (*format)->digitlang = LANG_NEUTRAL; (*format)->trimming = StringTrimmingCharacter; + (*format)->digitsub = StringDigitSubstituteUser; + /* tabstops */ + (*format)->tabcount = 0; + (*format)->firsttab = 0.0; + (*format)->tabs = NULL; return Ok; } @@ -53,6 +59,7 @@ GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat *format) if(!format) return InvalidParameter; + GdipFree(format->tabs); GdipFree(format); return Ok; @@ -60,12 +67,19 @@ GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat *format) GpStatus WINGDIPAPI GdipStringFormatGetGenericDefault(GpStringFormat **format) { + GpStatus stat; + if (!format) return InvalidParameter; - FIXME("stub: %p\n", format); + stat = GdipCreateStringFormat(0, LANG_NEUTRAL, format); + if(stat != Ok) + return stat; - return NotImplemented; + (*format)->align = StringAlignmentNear; + (*format)->vertalign = StringAlignmentNear; + + return Ok; } GpStatus WINGDIPAPI GdipGetStringFormatAlign(GpStringFormat *format, @@ -79,6 +93,18 @@ GpStatus WINGDIPAPI GdipGetStringFormatAlign(GpStringFormat *format, return Ok; } +GpStatus WINGDIPAPI GdipGetStringFormatDigitSubstitution(GDIPCONST GpStringFormat *format, + LANGID *language, StringDigitSubstitute *substitute) +{ + if(!format) + return InvalidParameter; + + if(language) *language = format->digitlang; + if(substitute) *substitute = format->digitsub; + + return Ok; +} + GpStatus WINGDIPAPI GdipGetStringFormatFlags(GDIPCONST GpStringFormat* format, INT* flags) { @@ -123,6 +149,32 @@ GpStatus WINGDIPAPI GdipGetStringFormatMeasurableCharacterRangeCount( return NotImplemented; } +GpStatus WINGDIPAPI GdipGetStringFormatTabStopCount(GDIPCONST GpStringFormat *format, + INT *count) +{ + if(!format || !count) + return InvalidParameter; + + *count = format->tabcount; + + return Ok; +} + +GpStatus WINGDIPAPI GdipGetStringFormatTabStops(GDIPCONST GpStringFormat *format, INT count, + REAL *firsttab, REAL *tabs) +{ + if(!format || !firsttab || !tabs) + return InvalidParameter; + + /* native simply crashes on count < 0 */ + if(count != 0) + memcpy(tabs, format->tabs, sizeof(REAL)*count); + + *firsttab = format->firsttab; + + return Ok; +} + GpStatus WINGDIPAPI GdipGetStringFormatTrimming(GpStringFormat *format, StringTrimming *trimming) { @@ -145,6 +197,19 @@ GpStatus WINGDIPAPI GdipSetStringFormatAlign(GpStringFormat *format, return Ok; } +/*FIXME: digit substitution actually not implemented, get/set only */ +GpStatus WINGDIPAPI GdipSetStringFormatDigitSubstitution(GpStringFormat *format, + LANGID language, StringDigitSubstitute substitute) +{ + if(!format) + return InvalidParameter; + + format->digitlang = language; + format->digitsub = substitute; + + return Ok; +} + GpStatus WINGDIPAPI GdipSetStringFormatHotkeyPrefix(GpStringFormat *format, INT hkpx) { @@ -178,6 +243,36 @@ GpStatus WINGDIPAPI GdipSetStringFormatMeasurableCharacterRanges(GpStringFormat* return NotImplemented; } +GpStatus WINGDIPAPI GdipSetStringFormatTabStops(GpStringFormat *format, REAL firsttab, + INT count, GDIPCONST REAL *tabs) +{ + if(!format || !tabs) + return InvalidParameter; + + if(count > 0){ + if(firsttab < 0.0) return NotImplemented; + /* first time allocation */ + if(format->tabcount == 0){ + format->tabs = GdipAlloc(sizeof(REAL)*count); + if(!format->tabs) + return OutOfMemory; + } + /* reallocation */ + if((format->tabcount < count) && (format->tabcount > 0)){ + REAL *ptr; + ptr = HeapReAlloc(GetProcessHeap(), 0, format->tabs, sizeof(REAL)*count); + if(!ptr) + return OutOfMemory; + format->tabs = ptr; + } + format->firsttab = firsttab; + format->tabcount = count; + memcpy(format->tabs, tabs, sizeof(REAL)*count); + } + + return Ok; +} + GpStatus WINGDIPAPI GdipSetStringFormatTrimming(GpStringFormat *format, StringTrimming trimming) { @@ -206,7 +301,41 @@ GpStatus WINGDIPAPI GdipCloneStringFormat(GDIPCONST GpStringFormat *format, GpSt **newFormat = *format; + if(format->tabcount > 0){ + (*newFormat)->tabs = GdipAlloc(sizeof(REAL) * format->tabcount); + if(!(*newFormat)->tabs){ + GdipFree(*newFormat); + return OutOfMemory; + } + memcpy((*newFormat)->tabs, format->tabs, sizeof(REAL) * format->tabcount); + } + else + (*newFormat)->tabs = NULL; + TRACE("%p %p\n",format,newFormat); return Ok; } + +GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **format) +{ + GpStatus stat; + + if(!format) + return InvalidParameter; + + stat = GdipCreateStringFormat(StringFormatFlagsNoFitBlackBox | + StringFormatFlagsLineLimit | + StringFormatFlagsNoClip, LANG_NEUTRAL, format); + if(stat != Ok) + return stat; + + (*format)->digitlang = LANG_NEUTRAL; + (*format)->digitsub = StringDigitSubstituteUser; + (*format)->trimming = StringTrimmingNone; + (*format)->hkprefix = HotkeyPrefixNone; + (*format)->align = StringAlignmentNear; + (*format)->vertalign = StringAlignmentNear; + + return Ok; +} diff --git a/dlls/gdiplus/tests/Makefile.in b/dlls/gdiplus/tests/Makefile.in index c5f8504de5b..7dba3daaaa7 100644 --- a/dlls/gdiplus/tests/Makefile.in +++ b/dlls/gdiplus/tests/Makefile.in @@ -7,6 +7,7 @@ IMPORTS = gdiplus user32 gdi32 kernel32 CTESTS = \ brush.c \ + customlinecap.c \ font.c \ graphics.c \ graphicspath.c \ diff --git a/dlls/gdiplus/tests/customlinecap.c b/dlls/gdiplus/tests/customlinecap.c new file mode 100644 index 00000000000..78a8c704830 --- /dev/null +++ b/dlls/gdiplus/tests/customlinecap.c @@ -0,0 +1,202 @@ +/* + * Unit test suite for customlinecap + * + * Copyright (C) 2008 Nikolay Sivov + * + * 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 "windows.h" +#include "gdiplus.h" +#include "wine/test.h" + +#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) +#define expectf(expected, got) ok(got == expected, "Expected %.2f, got %.2f\n", expected, got) + +static void test_constructor_destructor(void) +{ + GpCustomLineCap *custom; + GpPath *path, *path2; + GpStatus stat; + + stat = GdipCreatePath(FillModeAlternate, &path); + expect(Ok, stat); + stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0); + expect(Ok, stat); + + stat = GdipCreatePath(FillModeAlternate, &path2); + expect(Ok, stat); + stat = GdipAddPathRectangle(path2, 5.0, 5.0, 10.0, 10.0); + expect(Ok, stat); + + /* NULL args */ + stat = GdipCreateCustomLineCap(NULL, NULL, LineCapFlat, 0.0, NULL); + expect(InvalidParameter, stat); + stat = GdipCreateCustomLineCap(path, NULL, LineCapFlat, 0.0, NULL); + expect(InvalidParameter, stat); + stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, NULL); + expect(InvalidParameter, stat); + stat = GdipCreateCustomLineCap(NULL, NULL, LineCapFlat, 0.0, &custom); + expect(InvalidParameter, stat); + stat = GdipDeleteCustomLineCap(NULL); + expect(InvalidParameter, stat); + + /* valid args */ + stat = GdipCreateCustomLineCap(NULL, path2, LineCapFlat, 0.0, &custom); + expect(Ok, stat); + stat = GdipDeleteCustomLineCap(custom); + expect(Ok, stat); + /* it's strange but native returns NotImplemented on stroke == NULL */ + stat = GdipCreateCustomLineCap(path, NULL, LineCapFlat, 10.0, &custom); + todo_wine expect(NotImplemented, stat); + + GdipDeletePath(path2); + GdipDeletePath(path); +} + +static void test_linejoin(void) +{ + GpCustomLineCap *custom; + GpPath *path; + GpLineJoin join; + GpStatus stat; + + stat = GdipCreatePath(FillModeAlternate, &path); + expect(Ok, stat); + stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0); + expect(Ok, stat); + + stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom); + expect(Ok, stat); + + /* NULL args */ + stat = GdipGetCustomLineCapStrokeJoin(NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipGetCustomLineCapStrokeJoin(custom, NULL); + expect(InvalidParameter, stat); + stat = GdipGetCustomLineCapStrokeJoin(NULL, &join); + expect(InvalidParameter, stat); + stat = GdipSetCustomLineCapStrokeJoin(NULL, LineJoinBevel); + expect(InvalidParameter, stat); + + /* LineJoinMiter is default */ + stat = GdipGetCustomLineCapStrokeJoin(custom, &join); + expect(Ok, stat); + expect(LineJoinMiter, join); + + /* set/get */ + stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinBevel); + expect(Ok, stat); + stat = GdipGetCustomLineCapStrokeJoin(custom, &join); + expect(Ok, stat); + expect(LineJoinBevel, join); + stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinRound); + expect(Ok, stat); + stat = GdipGetCustomLineCapStrokeJoin(custom, &join); + expect(Ok, stat); + expect(LineJoinRound, join); + stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinMiterClipped); + expect(Ok, stat); + stat = GdipGetCustomLineCapStrokeJoin(custom, &join); + expect(Ok, stat); + expect(LineJoinMiterClipped, join); + + GdipDeleteCustomLineCap(custom); + GdipDeletePath(path); +} + +static void test_inset(void) +{ + GpCustomLineCap *custom; + GpPath *path; + REAL inset; + GpStatus stat; + + stat = GdipCreatePath(FillModeAlternate, &path); + expect(Ok, stat); + stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0); + expect(Ok, stat); + + stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom); + expect(Ok, stat); + + /* NULL args */ + stat = GdipGetCustomLineCapBaseInset(NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipGetCustomLineCapBaseInset(NULL, &inset); + expect(InvalidParameter, stat); + stat = GdipGetCustomLineCapBaseInset(custom, NULL); + expect(InvalidParameter, stat); + /* valid args */ + inset = (REAL)0xdeadbeef; + stat = GdipGetCustomLineCapBaseInset(custom, &inset); + expect(Ok, stat); + expectf(0.0, inset); + + GdipDeleteCustomLineCap(custom); + GdipDeletePath(path); +} + +static void test_scale(void) +{ + GpCustomLineCap *custom; + GpPath *path; + REAL scale; + GpStatus stat; + + stat = GdipCreatePath(FillModeAlternate, &path); + expect(Ok, stat); + stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0); + expect(Ok, stat); + + stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom); + expect(Ok, stat); + + /* NULL args */ + stat = GdipGetCustomLineCapWidthScale(NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipGetCustomLineCapWidthScale(NULL, &scale); + expect(InvalidParameter, stat); + stat = GdipGetCustomLineCapWidthScale(custom, NULL); + expect(InvalidParameter, stat); + /* valid args */ + scale = (REAL)0xdeadbeef; + stat = GdipGetCustomLineCapWidthScale(custom, &scale); + expect(Ok, stat); + expectf(1.0, scale); + + GdipDeleteCustomLineCap(custom); + GdipDeletePath(path); +} + +START_TEST(customlinecap) +{ + struct GdiplusStartupInput gdiplusStartupInput; + ULONG_PTR gdiplusToken; + + gdiplusStartupInput.GdiplusVersion = 1; + gdiplusStartupInput.DebugEventCallback = NULL; + gdiplusStartupInput.SuppressBackgroundThread = 0; + gdiplusStartupInput.SuppressExternalCodecs = 0; + + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + test_constructor_destructor(); + test_linejoin(); + test_inset(); + test_scale(); + + GdiplusShutdown(gdiplusToken); +} diff --git a/dlls/gdiplus/tests/font.c b/dlls/gdiplus/tests/font.c index ab0f814fa62..8ce0ec63c37 100644 --- a/dlls/gdiplus/tests/font.c +++ b/dlls/gdiplus/tests/font.c @@ -96,6 +96,15 @@ static void test_logfont(void) GdipCreateFromHDC(hdc, &graphics); memset(&lfw, 0, sizeof(LOGFONTW)); memset(&lfw2, 0xff, sizeof(LOGFONTW)); + + /* empty FaceName */ + lfw.lfFaceName[0] = 0; + stat = GdipCreateFontFromLogfontW(hdc, &lfw, &font); + +todo_wine { + expect(NotTrueTypeFont, stat); +} + memcpy(&lfw.lfFaceName, arial, 6 * sizeof(WCHAR)); stat = GdipCreateFontFromLogfontW(hdc, &lfw, &font); diff --git a/dlls/gdiplus/tests/pen.c b/dlls/gdiplus/tests/pen.c index ad484ce4776..d75e510f9e4 100644 --- a/dlls/gdiplus/tests/pen.c +++ b/dlls/gdiplus/tests/pen.c @@ -226,6 +226,55 @@ static void test_dasharray(void) GdipDeletePen(pen); } +static void test_customcap(void) +{ + GpPen *pen; + GpStatus status; + GpCustomLineCap *custom; + + status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); + expect(Ok, status); + + /* NULL args */ + status = GdipGetPenCustomStartCap(NULL, NULL); + expect(InvalidParameter, status); + status = GdipGetPenCustomStartCap(pen, NULL); + expect(InvalidParameter, status); + status = GdipGetPenCustomStartCap(NULL, &custom); + expect(InvalidParameter, status); + + status = GdipGetPenCustomEndCap(NULL, NULL); + expect(InvalidParameter, status); + status = GdipGetPenCustomEndCap(pen, NULL); + expect(InvalidParameter, status); + status = GdipGetPenCustomEndCap(NULL, &custom); + expect(InvalidParameter, status); + + /* native crashes on pen == NULL, custom != NULL */ + status = GdipSetPenCustomStartCap(NULL, NULL); + expect(InvalidParameter, status); + status = GdipSetPenCustomStartCap(pen, NULL); + expect(InvalidParameter, status); + + status = GdipSetPenCustomEndCap(NULL, NULL); + expect(InvalidParameter, status); + status = GdipSetPenCustomEndCap(pen, NULL); + expect(InvalidParameter, status); + + /* get without setting previously */ + custom = (GpCustomLineCap*)0xdeadbeef; + status = GdipGetPenCustomEndCap(pen, &custom); + expect(Ok, status); + ok(custom == NULL,"Expect CustomCap == NULL\n"); + + custom = (GpCustomLineCap*)0xdeadbeef; + status = GdipGetPenCustomStartCap(pen, &custom); + expect(Ok, status); + ok(custom == NULL,"Expect CustomCap == NULL\n"); + + GdipDeletePen(pen); +} + START_TEST(pen) { struct GdiplusStartupInput gdiplusStartupInput; @@ -244,6 +293,7 @@ START_TEST(pen) test_constructor_destructor2(); test_brushfill(); test_dasharray(); + test_customcap(); GdiplusShutdown(gdiplusToken); } diff --git a/dlls/gdiplus/tests/stringformat.c b/dlls/gdiplus/tests/stringformat.c index 3f112e0f74c..93319128f28 100644 --- a/dlls/gdiplus/tests/stringformat.c +++ b/dlls/gdiplus/tests/stringformat.c @@ -23,6 +23,7 @@ #include "wine/test.h" #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) +#define expectf(expected, got) ok(got == expected, "Expected %.2f, got %.2f\n", expected, got) static void test_constructor(void) { @@ -31,19 +32,24 @@ static void test_constructor(void) INT n; StringAlignment align, valign; StringTrimming trimming; + StringDigitSubstitute digitsub; + LANGID digitlang; - stat = GdipCreateStringFormat(0, 0, &format); + stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format); expect(Ok, stat); GdipGetStringFormatAlign(format, &align); GdipGetStringFormatLineAlign(format, &valign); GdipGetStringFormatHotkeyPrefix(format, &n); GdipGetStringFormatTrimming(format, &trimming); + GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub); expect(HotkeyPrefixNone, n); expect(StringAlignmentNear, align); expect(StringAlignmentNear, align); expect(StringTrimmingCharacter, trimming); + expect(StringDigitSubstituteUser, digitsub); + expect(LANG_NEUTRAL, digitlang); stat = GdipDeleteStringFormat(format); expect(Ok, stat); @@ -70,6 +76,247 @@ todo_wine expect(Ok, stat); } +static void test_digitsubstitution(void) +{ + GpStringFormat *format; + GpStatus stat; + StringDigitSubstitute digitsub; + LANGID digitlang; + + stat = GdipCreateStringFormat(0, LANG_RUSSIAN, &format); + expect(Ok, stat); + + /* NULL arguments */ + stat = GdipGetStringFormatDigitSubstitution(NULL, NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipGetStringFormatDigitSubstitution(format, NULL, NULL); + expect(Ok, stat); + stat = GdipGetStringFormatDigitSubstitution(NULL, &digitlang, NULL); + expect(InvalidParameter, stat); + stat = GdipGetStringFormatDigitSubstitution(NULL, NULL, &digitsub); + expect(InvalidParameter, stat); + stat = GdipGetStringFormatDigitSubstitution(NULL, &digitlang, &digitsub); + expect(InvalidParameter, stat); + stat = GdipSetStringFormatDigitSubstitution(NULL, LANG_NEUTRAL, StringDigitSubstituteNone); + expect(InvalidParameter, stat); + + /* try to get both and one by one */ + stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub); + expect(Ok, stat); + expect(StringDigitSubstituteUser, digitsub); + expect(LANG_NEUTRAL, digitlang); + + digitsub = StringDigitSubstituteNone; + stat = GdipGetStringFormatDigitSubstitution(format, NULL, &digitsub); + expect(Ok, stat); + expect(StringDigitSubstituteUser, digitsub); + + digitlang = LANG_RUSSIAN; + stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, NULL); + expect(Ok, stat); + expect(LANG_NEUTRAL, digitlang); + + /* set/get */ + stat = GdipSetStringFormatDigitSubstitution(format, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL), + StringDigitSubstituteUser); + expect(Ok, stat); + digitsub = StringDigitSubstituteNone; + digitlang = LANG_RUSSIAN; + stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub); + expect(Ok, stat); + expect(StringDigitSubstituteUser, digitsub); + expect(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL), digitlang); + + stat = GdipDeleteStringFormat(format); + expect(Ok, stat); +} + +static void test_getgenerictypographic(void) +{ + GpStringFormat *format; + GpStatus stat; + INT flags; + INT n; + StringAlignment align, valign; + StringTrimming trimming; + StringDigitSubstitute digitsub; + LANGID digitlang; + INT tabcount; + + /* NULL arg */ + stat = GdipStringFormatGetGenericTypographic(NULL); + expect(InvalidParameter, stat); + + stat = GdipStringFormatGetGenericTypographic(&format); + expect(Ok, stat); + + GdipGetStringFormatFlags(format, &flags); + GdipGetStringFormatAlign(format, &align); + GdipGetStringFormatLineAlign(format, &valign); + GdipGetStringFormatHotkeyPrefix(format, &n); + GdipGetStringFormatTrimming(format, &trimming); + GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub); + GdipGetStringFormatTabStopCount(format, &tabcount); + + expect((StringFormatFlagsNoFitBlackBox |StringFormatFlagsLineLimit | StringFormatFlagsNoClip), + flags); + expect(HotkeyPrefixNone, n); + expect(StringAlignmentNear, align); + expect(StringAlignmentNear, align); + expect(StringTrimmingNone, trimming); + expect(StringDigitSubstituteUser, digitsub); + expect(LANG_NEUTRAL, digitlang); + expect(0, tabcount); + + stat = GdipDeleteStringFormat(format); + expect(Ok, stat); +} + +static REAL tabstops[] = {0.0, 10.0, 2.0}; +static void test_tabstops(void) +{ + GpStringFormat *format; + GpStatus stat; + INT count; + REAL tabs[3]; + REAL firsttab; + + stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format); + expect(Ok, stat); + + /* NULL */ + stat = GdipGetStringFormatTabStopCount(NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipGetStringFormatTabStopCount(NULL, &count); + expect(InvalidParameter, stat); + stat = GdipGetStringFormatTabStopCount(format, NULL); + expect(InvalidParameter, stat); + + stat = GdipSetStringFormatTabStops(NULL, 0.0, 0, NULL); + expect(InvalidParameter, stat); + stat = GdipSetStringFormatTabStops(format, 0.0, 0, NULL); + expect(InvalidParameter, stat); + stat = GdipSetStringFormatTabStops(NULL, 0.0, 0, tabstops); + expect(InvalidParameter, stat); + + stat = GdipGetStringFormatTabStops(NULL, 0, NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipGetStringFormatTabStops(format, 0, NULL, NULL); + expect(InvalidParameter, stat); + stat = GdipGetStringFormatTabStops(NULL, 0, &firsttab, NULL); + expect(InvalidParameter, stat); + stat = GdipGetStringFormatTabStops(NULL, 0, NULL, tabs); + expect(InvalidParameter, stat); + stat = GdipGetStringFormatTabStops(format, 0, &firsttab, NULL); + expect(InvalidParameter, stat); + stat = GdipGetStringFormatTabStops(format, 0, NULL, tabs); + expect(InvalidParameter, stat); + + /* not NULL */ + stat = GdipGetStringFormatTabStopCount(format, &count); + expect(Ok, stat); + expect(0, count); + /* negative tabcount */ + stat = GdipSetStringFormatTabStops(format, 0.0, -1, tabstops); + expect(Ok, stat); + count = -1; + stat = GdipGetStringFormatTabStopCount(format, &count); + expect(Ok, stat); + expect(0, count); + + stat = GdipSetStringFormatTabStops(format, -10.0, 0, tabstops); + expect(Ok, stat); + stat = GdipSetStringFormatTabStops(format, -10.0, 1, tabstops); + expect(NotImplemented, stat); + + firsttab = -1.0; + tabs[0] = tabs[1] = tabs[2] = -1.0; + stat = GdipGetStringFormatTabStops(format, 0, &firsttab, tabs); + expect(Ok, stat); + expectf(-1.0, tabs[0]); + expectf(-1.0, tabs[1]); + expectf(-1.0, tabs[2]); + expectf(0.0, firsttab); + + stat = GdipSetStringFormatTabStops(format, +0.0, 3, tabstops); + expect(Ok, stat); + count = 0; + stat = GdipGetStringFormatTabStopCount(format, &count); + expect(Ok, stat); + expect(3, count); + + firsttab = -1.0; + tabs[0] = tabs[1] = tabs[2] = -1.0; + stat = GdipGetStringFormatTabStops(format, 3, &firsttab, tabs); + expect(Ok, stat); + expectf(0.0, tabs[0]); + expectf(10.0, tabs[1]); + expectf(2.0, tabs[2]); + expectf(0.0, firsttab); + + stat = GdipSetStringFormatTabStops(format, 10.0, 3, tabstops); + expect(Ok, stat); + firsttab = -1.0; + tabs[0] = tabs[1] = tabs[2] = -1.0; + stat = GdipGetStringFormatTabStops(format, 0, &firsttab, tabs); + expect(Ok, stat); + expectf(-1.0, tabs[0]); + expectf(-1.0, tabs[1]); + expectf(-1.0, tabs[2]); + expectf(10.0, firsttab); + + /* zero tabcount, after valid setting to 3 */ + stat = GdipSetStringFormatTabStops(format, 0.0, 0, tabstops); + expect(Ok, stat); + count = 0; + stat = GdipGetStringFormatTabStopCount(format, &count); + expect(Ok, stat); + expect(3, count); + + stat = GdipDeleteStringFormat(format); + expect(Ok, stat); +} + +static void test_getgenericdefault(void) +{ + GpStringFormat *format; + GpStatus stat; + + INT flags; + INT n; + StringAlignment align, valign; + StringTrimming trimming; + StringDigitSubstitute digitsub; + LANGID digitlang; + INT tabcount; + + /* NULL arg */ + stat = GdipStringFormatGetGenericDefault(NULL); + expect(InvalidParameter, stat); + + stat = GdipStringFormatGetGenericDefault(&format); + expect(Ok, stat); + + GdipGetStringFormatFlags(format, &flags); + GdipGetStringFormatAlign(format, &align); + GdipGetStringFormatLineAlign(format, &valign); + GdipGetStringFormatHotkeyPrefix(format, &n); + GdipGetStringFormatTrimming(format, &trimming); + GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub); + GdipGetStringFormatTabStopCount(format, &tabcount); + + expect(0, flags); + expect(HotkeyPrefixNone, n); + expect(StringAlignmentNear, align); + expect(StringAlignmentNear, align); + expect(StringTrimmingCharacter, trimming); + expect(StringDigitSubstituteUser, digitsub); + expect(LANG_NEUTRAL, digitlang); + expect(0, tabcount); + + stat = GdipDeleteStringFormat(format); + expect(Ok, stat); +} START_TEST(stringformat) { @@ -85,6 +332,10 @@ START_TEST(stringformat) test_constructor(); test_characterrange(); + test_digitsubstitution(); + test_getgenerictypographic(); + test_tabstops(); + test_getgenericdefault(); GdiplusShutdown(gdiplusToken); } diff --git a/dlls/inetmib1/main.c b/dlls/inetmib1/main.c index e5b44ce5595..d19f048364b 100644 --- a/dlls/inetmib1/main.c +++ b/dlls/inetmib1/main.c @@ -1169,6 +1169,9 @@ static struct mibImplementation supportedIDs[] = { }; static UINT minSupportedIDLength; +/***************************************************************************** + * SnmpExtensionInit [INETMIB1.@] + */ BOOL WINAPI SnmpExtensionInit(DWORD dwUptimeReference, HANDLE *phSubagentTrapEvent, AsnObjectIdentifier *pFirstSupportedRegion) { @@ -1228,6 +1231,9 @@ static struct mibImplementation *findSupportedQuery(UINT *ids, UINT idLength, return impl; } +/***************************************************************************** + * SnmpExtensionQuery [INETMIB1.@] + */ BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, AsnInteger32 *pErrorStatus, AsnInteger32 *pErrorIndex) { @@ -1297,6 +1303,9 @@ BOOL WINAPI SnmpExtensionQuery(BYTE bPduType, SnmpVarBindList *pVarBindList, return TRUE; } +/***************************************************************************** + * DllMain [INETMIB1.@] + */ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); diff --git a/dlls/kernel32/tests/codepage.c b/dlls/kernel32/tests/codepage.c index e8908f75c45..0c5d6978a64 100644 --- a/dlls/kernel32/tests/codepage.c +++ b/dlls/kernel32/tests/codepage.c @@ -2,6 +2,7 @@ * Unit tests for code page to/from unicode translations * * Copyright (c) 2002 Dmitry Timoshkov + * Copyright (c) 2008 Colin Finck * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -203,17 +204,150 @@ static void test_overlapped_buffers(void) char buf[256]; int ret; + SetLastError(0xdeadbeef); memcpy((WCHAR *)(buf + 1), strW, sizeof(strW)); ret = WideCharToMultiByte(CP_ACP, 0, (WCHAR *)(buf + 1), -1, buf, sizeof(buf), NULL, NULL); ok(ret == sizeof(strA), "unexpected ret %d\n", ret); ok(!memcmp(buf, strA, sizeof(strA)), "conversion failed: %s\n", buf); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); +} + +static void test_string_conversion(LPBOOL bUsedDefaultChar) +{ + char mbc; + char mbs[5]; + int ret; + WCHAR wc1 = 228; /* Western Windows-1252 character */ + WCHAR wc2 = 1088; /* Russian Windows-1251 character not displayable for Windows-1252 */ + WCHAR wcs[5] = {'T', 'h', 1088, 'i', 0}; /* String with ASCII characters and a Russian character */ + WCHAR dbwcs[3] = {28953, 25152, 0}; /* String with Chinese (codepage 950) characters */ + + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(1252, 0, &wc1, 1, &mbc, 1, NULL, bUsedDefaultChar); + ok(ret == 1, "ret is %d\n", ret); + ok(mbc == -28, "mbc is %d\n", mbc); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(1252, 0, &wc2, 1, &mbc, 1, NULL, bUsedDefaultChar); + ok(ret == 1, "ret is %d\n", ret); + ok(mbc == 63, "mbc is %d\n", mbc); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(1251, 0, &wc2, 1, &mbc, 1, NULL, bUsedDefaultChar); + ok(ret == 1, "ret is %d\n", ret); + ok(mbc == -16, "mbc is %d\n", mbc); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(1251, 0, &wc1, 1, &mbc, 1, NULL, bUsedDefaultChar); + ok(ret == 1, "ret is %d\n", ret); + ok(mbc == 97, "mbc is %d\n", mbc); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + + /* This call triggers the last Win32 error */ + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(1252, 0, wcs, -1, &mbc, 1, NULL, bUsedDefaultChar); + ok(ret == 0, "ret is %d\n", ret); + ok(mbc == 84, "mbc is %d\n", mbc); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() is %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(1252, 0, wcs, -1, mbs, sizeof(mbs), NULL, bUsedDefaultChar); + ok(ret == 5, "ret is %d\n", ret); + ok(!strcmp(mbs, "Th?i"), "mbs is %s\n", mbs); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + mbs[0] = 0; + + /* WideCharToMultiByte mustn't add any null character automatically. + So in this case, we should get the same string again, even if we only copied the first three bytes. */ + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(1252, 0, wcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar); + ok(ret == 3, "ret is %d\n", ret); + ok(!strcmp(mbs, "Th?i"), "mbs is %s\n", mbs); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + ZeroMemory(mbs, 5); + + /* Now this shouldn't be the case like above as we zeroed the complete string buffer. */ + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(1252, 0, wcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar); + ok(ret == 3, "ret is %d\n", ret); + ok(!strcmp(mbs, "Th?"), "mbs is %s\n", mbs); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + + /* Double-byte tests */ + ret = WideCharToMultiByte(1252, 0, dbwcs, 3, mbs, sizeof(mbs), NULL, bUsedDefaultChar); + ok(ret == 3, "ret is %d\n", ret); + ok(!strcmp(mbs, "??"), "mbs is %s\n", mbs); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(950, 0, dbwcs, -1, mbs, sizeof(mbs), NULL, bUsedDefaultChar); + ok(ret == 5, "ret is %d\n", ret); + ok(!strcmp(mbs, "µH©Ò"), "mbs is %s\n", mbs); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(950, 0, dbwcs, 1, &mbc, 1, NULL, bUsedDefaultChar); + ok(ret == 0, "ret is %d\n", ret); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetLastError() is %u\n", GetLastError()); + ZeroMemory(mbs, 5); + + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(950, 0, dbwcs, 1, mbs, sizeof(mbs), NULL, bUsedDefaultChar); + ok(ret == 2, "ret is %d\n", ret); + ok(!strcmp(mbs, "µH"), "mbs is %s\n", mbs); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + + /* Length-only tests */ + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(1252, 0, &wc2, 1, NULL, 0, NULL, bUsedDefaultChar); + ok(ret == 1, "ret is %d\n", ret); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(1252, 0, wcs, -1, NULL, 0, NULL, bUsedDefaultChar); + ok(ret == 5, "ret is %d\n", ret); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == TRUE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(950, 0, dbwcs, 1, NULL, 0, NULL, bUsedDefaultChar); + ok(ret == 2, "ret is %d\n", ret); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = WideCharToMultiByte(950, 0, dbwcs, -1, NULL, 0, NULL, bUsedDefaultChar); + ok(ret == 5, "ret is %d\n", ret); + if(bUsedDefaultChar) ok(*bUsedDefaultChar == FALSE, "bUsedDefaultChar is %d\n", *bUsedDefaultChar); + ok(GetLastError() == 0xdeadbeef, "GetLastError() is %u\n", GetLastError()); } START_TEST(codepage) { + BOOL bUsedDefaultChar; + test_destination_buffer(); test_null_source(); test_negative_source_length(); test_negative_dest_length(); test_overlapped_buffers(); + + /* WideCharToMultiByte has two code pathes, test both here */ + test_string_conversion(NULL); + test_string_conversion(&bUsedDefaultChar); } diff --git a/dlls/kernel32/tests/profile.c b/dlls/kernel32/tests/profile.c index 91ff98223c5..46dfe72b40b 100644 --- a/dlls/kernel32/tests/profile.c +++ b/dlls/kernel32/tests/profile.c @@ -363,6 +363,7 @@ static void test_GetPrivateProfileString(void) { DWORD ret; CHAR buf[MAX_PATH]; + CHAR def_val[MAX_PATH]; CHAR path[MAX_PATH]; CHAR windir[MAX_PATH]; LPSTR tempfile; @@ -416,14 +417,18 @@ static void test_GetPrivateProfileString(void) /* lpAppName is empty, lpDefault has trailing blank characters */ lstrcpyA(buf, "kumquat"); - ret = GetPrivateProfileStringA("", "name1", "default ", + /* lpDefault must be writeable (trailing blanks are removed inplace in win9x) */ + lstrcpyA(def_val, "default "); + ret = GetPrivateProfileStringA("", "name1", def_val, buf, MAX_PATH, filename); ok(ret == 7, "Expected 7, got %d\n", ret); ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf); /* lpAppName is empty, many blank characters in lpDefault */ lstrcpyA(buf, "kumquat"); - ret = GetPrivateProfileStringA("", "name1", "one two ", + /* lpDefault must be writeable (trailing blanks are removed inplace in win9x) */ + lstrcpyA(def_val, "one two "); + ret = GetPrivateProfileStringA("", "name1", def_val, buf, MAX_PATH, filename); ok(ret == 7, "Expected 7, got %d\n", ret); ok(!lstrcmpA(buf, "one two"), "Expected \"one two\", got \"%s\"\n", buf); @@ -473,7 +478,9 @@ static void test_GetPrivateProfileString(void) /* lpKeyName is empty, lpDefault has trailing blank characters */ lstrcpyA(buf, "kumquat"); - ret = GetPrivateProfileStringA("section1", "", "default ", + /* lpDefault must be writeable (trailing blanks are removed inplace in win9x) */ + lstrcpyA(def_val, "default "); + ret = GetPrivateProfileStringA("section1", "", def_val, buf, MAX_PATH, filename); ok(ret == 7, "Expected 7, got %d\n", ret); ok(!lstrcmpA(buf, "default"), "Expected \"default\", got \"%s\"\n", buf); diff --git a/dlls/kernel32/tests/sync.c b/dlls/kernel32/tests/sync.c index c7a949c4ee4..02904f72f3b 100644 --- a/dlls/kernel32/tests/sync.c +++ b/dlls/kernel32/tests/sync.c @@ -609,11 +609,45 @@ static void CALLBACK timer_queue_cb5(PVOID p, BOOLEAN timedOut) Sleep(delay); } +static void CALLBACK timer_queue_cb6(PVOID p, BOOLEAN timedOut) +{ + struct timer_queue_data1 *d = p; + ok(timedOut, "Timer callbacks should always time out\n"); + /* This tests an original implementation bug where a deleted timer may get + to run, but it is tricky to set up. */ + if (d->q && d->num_calls++ == 0) + { + /* First run: delete ourselves, then insert and remove a timer + that goes in front of us in the sorted timeout list. Once + removed, we will still timeout at the faster timer's due time, + but this should be a no-op if we are bug-free. There should + not be a second run. We can test the value of num_calls later. */ + BOOL ret; + HANDLE t; + + /* The delete will pend while we are in this callback. */ + SetLastError(0xdeadbeef); + ret = pDeleteTimerQueueTimer(d->q, d->t, NULL); + ok(!ret, "DeleteTimerQueueTimer\n"); + ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueTimer\n"); + + ret = pCreateTimerQueueTimer(&t, d->q, timer_queue_cb1, NULL, 100, 0, 0); + ok(ret, "CreateTimerQueueTimer\n"); + ok(t != NULL, "CreateTimerQueueTimer\n"); + + ret = pDeleteTimerQueueTimer(d->q, t, INVALID_HANDLE_VALUE); + ok(ret, "DeleteTimerQueueTimer\n"); + + /* Now we stay alive by hanging around in the callback. */ + Sleep(500); + } +} + static void test_timer_queue(void) { HANDLE q, t1, t2, t3, t4, t5; int n1, n2, n3, n4, n5; - struct timer_queue_data1 d2, d3, d4; + struct timer_queue_data1 d1, d2, d3, d4; HANDLE e, et1, et2; BOOL ret; @@ -824,6 +858,83 @@ static void test_timer_queue(void) ok(d2.num_calls == d2.max_calls, "DeleteTimerQueueTimer\n"); ok(d3.num_calls == d3.max_calls, "ChangeTimerQueueTimer\n"); ok(d4.num_calls == 1, "Timer flagged for deletion incorrectly\n"); + + /* Test an obscure bug that was in the original implementation. */ + q = pCreateTimerQueue(); + ok(q != NULL, "CreateTimerQueue\n"); + + /* All the work is done in the callback. */ + d1.t = t1 = NULL; + d1.num_calls = 0; + d1.q = q; + ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb6, &d1, 100, + 100, WT_EXECUTELONGFUNCTION); + d1.t = t1; + ok(ret, "CreateTimerQueueTimer\n"); + ok(t1 != NULL, "CreateTimerQueueTimer\n"); + + Sleep(750); + + SetLastError(0xdeadbeef); + ret = pDeleteTimerQueueEx(q, NULL); + ok(!ret, "DeleteTimerQueueEx\n"); + ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n"); + ok(d1.num_calls == 1, "DeleteTimerQueueTimer\n"); + + /* Test functions on the default timer queue. */ + t1 = NULL; + n1 = 0; + ret = pCreateTimerQueueTimer(&t1, NULL, timer_queue_cb1, &n1, 1000, + 1000, 0); + ok(ret, "CreateTimerQueueTimer, default queue\n"); + ok(t1 != NULL, "CreateTimerQueueTimer, default queue\n"); + + ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000); + ok(ret, "ChangeTimerQueueTimer, default queue\n"); + + ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE); + ok(ret, "DeleteTimerQueueTimer, default queue\n"); + + /* Try mixing default and non-default queues. Apparently this works. */ + q = pCreateTimerQueue(); + ok(q != NULL, "CreateTimerQueue\n"); + + t1 = NULL; + n1 = 0; + ret = pCreateTimerQueueTimer(&t1, q, timer_queue_cb1, &n1, 1000, + 1000, 0); + ok(ret, "CreateTimerQueueTimer\n"); + ok(t1 != NULL, "CreateTimerQueueTimer\n"); + + t2 = NULL; + n2 = 0; + ret = pCreateTimerQueueTimer(&t2, NULL, timer_queue_cb1, &n2, 1000, + 1000, 0); + ok(ret, "CreateTimerQueueTimer\n"); + ok(t2 != NULL, "CreateTimerQueueTimer\n"); + + ret = pChangeTimerQueueTimer(NULL, t1, 2000, 2000); + ok(ret, "ChangeTimerQueueTimer\n"); + + ret = pChangeTimerQueueTimer(q, t2, 2000, 2000); + ok(ret, "ChangeTimerQueueTimer\n"); + + ret = pDeleteTimerQueueTimer(NULL, t1, INVALID_HANDLE_VALUE); + ok(ret, "DeleteTimerQueueTimer\n"); + + ret = pDeleteTimerQueueTimer(q, t2, INVALID_HANDLE_VALUE); + ok(ret, "DeleteTimerQueueTimer\n"); + + /* Try to delete the default queue? In any case: not allowed. */ + SetLastError(0xdeadbeef); + ret = pDeleteTimerQueueEx(NULL, NULL); + ok(!ret, "DeleteTimerQueueEx\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "DeleteTimerQueueEx\n"); + + SetLastError(0xdeadbeef); + ret = pDeleteTimerQueueEx(q, NULL); + ok(!ret, "DeleteTimerQueueEx\n"); + ok(GetLastError() == ERROR_IO_PENDING, "DeleteTimerQueueEx\n"); } START_TEST(sync) diff --git a/dlls/mlang/tests/mlang.c b/dlls/mlang/tests/mlang.c index 858d9fecb06..b5d77f72fc5 100644 --- a/dlls/mlang/tests/mlang.c +++ b/dlls/mlang/tests/mlang.c @@ -1111,6 +1111,177 @@ static void test_ConvertINetUnicodeToMultiByte(void) "Expected %u, got %u\n", lstrlenW(src) + 1, destsz); } +static void test_JapaneseConversion(void) +{ + /* Data */ + static WCHAR unc_jp[9][12] = { + {9,0x31,0x20,0x3042,0x3044,0x3046,0x3048,0x304a,0x000d,0x000a}, + {9,0x31,0x20,0x30a2,0x30a4,0x30a6,0x30a8,0x30aa,0x000d,0x000a}, + {9,0x31,0x20,0xff71,0xff72,0xff73,0xff74,0xff75,0x000d,0x000a}, + {9,0x31,0x20,0x3041,0x3043,0x3045,0x3047,0x3049,0x000d,0x000a}, + {9,0x31,0x20,0x30a1,0x30a3,0x30a5,0x30a7,0x30a9,0x000d,0x000a}, + {9,0x31,0x20,0xff67,0xff68,0xff69,0xff6a,0xff6b,0x000d,0x000a}, + {9,0x31,0x20,0x300c,0x65e5,0x672c,0x8a9e,0x300d,0x000d,0x000a}, + {7,0x31,0x20,0x25c7,0x25c7,0x3012,0x000d,0x000a}, + {11,0x31,0x20,0x203b,0x3010,0x0074,0x0065,0x0073,0x0074,0x3011,0x000d,0x000a} + }; + static CHAR jis_jp[9][27] = { + {20,0x31,0x20,0x1b,0x24,0x42,0x24,0x22,0x24,0x24,0x24,0x26,0x24,0x28, + 0x24,0x2a,0x1b,0x28,0x42,0x0d,0x0a}, + {20,0x31,0x20,0x1b,0x24,0x42,0x25,0x22,0x25,0x24,0x25,0x26,0x25,0x28,\ + 0x25,0x2a,0x1b,0x28,0x42,0x0d,0x0a}, + {20,0x31,0x20,0x1b,0x24,0x42,0x25,0x22,0x25,0x24,0x25,0x26,0x25,0x28,\ + 0x25,0x2a,0x1b,0x28,0x42,0x0d,0x0a}, + {20,0x31,0x20,0x1b,0x24,0x42,0x24,0x21,0x24,0x23,0x24,0x25,0x24,0x27,\ + 0x24,0x29,0x1b,0x28,0x42,0x0d,0x0a}, + {20,0x31,0x20,0x1b,0x24,0x42,0x25,0x21,0x25,0x23,0x25,0x25,0x25,0x27,\ + 0x25,0x29,0x1b,0x28,0x42,0x0d,0x0a}, + {20,0x31,0x20,0x1b,0x24,0x42,0x25,0x21,0x25,0x23,0x25,0x25,0x25,0x27,\ + 0x25,0x29,0x1b,0x28,0x42,0x0d,0x0a}, + {20,0x31,0x20,0x1b,0x24,0x42,0x21,0x56,0x46,0x7c,0x4b,0x5c,0x38,0x6c,\ + 0x21,0x57,0x1b,0x28,0x42,0x0d,0x0a}, + {16,0x31,0x20,0x1b,0x24,0x42,0x21,0x7e,0x21,0x7e,0x22,0x29,0x1b,0x28,\ + 0x42,0x0d,0x0a}, + {26,0x31,0x20,0x1b,0x24,0x42,0x22,0x28,0x21,0x5a,0x1b,0x28,0x42,0x74,\ + 0x65,0x73,0x74,0x1b,0x24,0x42,0x21,0x5b,0x1b,0x28,0x42,0x0d,0x0a} + }; + static CHAR sjis_jp[9][15] = { + {14,0x31,0x20,0x82,0xa0,0x82,0xa2,0x82,0xa4,0x82,0xa6,0x82,0xa8,0x0d,0x0a}, + {14,0x31,0x20,0x83,0x41,0x83,0x43,0x83,0x45,0x83,0x47,0x83,0x49,0x0d,0x0a}, + {9,0x31,0x20,0xb1,0xb2,0xb3,0xb4,0xb5,0x0d,0x0a}, + {14,0x31,0x20,0x82,0x9f,0x82,0xa1,0x82,0xa3,0x82,0xa5,0x82,0xa7,0x0d,0x0a}, + {14,0x31,0x20,0x83,0x40,0x83,0x42,0x83,0x44,0x83,0x46,0x83,0x48,0x0d,0x0a}, + {9,0x31,0x20,0xa7,0xa8,0xa9,0xaa,0xab,0x0d,0x0a}, + {14,0x31,0x20,0x81,0x75,0x93,0xfa,0x96,0x7b,0x8c,0xea,0x81,0x76,0x0d,0x0a}, + {10,0x31,0x20,0x81,0x9e,0x81,0x9e,0x81,0xa7,0x0d,0x0a}, + {14,0x31,0x20,0x81,0xa6,0x81,0x79,0x74,0x65,0x73,0x74,0x81,0x7a,0x0d,0x0a} + }; + static CHAR euc_jp[9][15] = { + {14,0x31,0x20,0xa4,0xa2,0xa4,0xa4,0xa4,0xa6,0xa4,0xa8,0xa4,0xaa,0x0d,0x0a}, + {14,0x31,0x20,0xa5,0xa2,0xa5,0xa4,0xa5,0xa6,0xa5,0xa8,0xa5,0xaa,0x0d,0x0a}, + {14,0x31,0x20,0x8e,0xb1,0x8e,0xb2,0x8e,0xb3,0x8e,0xb4,0x8e,0xb5,0x0d,0x0a}, + {14,0x31,0x20,0xa4,0xa1,0xa4,0xa3,0xa4,0xa5,0xa4,0xa7,0xa4,0xa9,0x0d,0x0a}, + {14,0x31,0x20,0xa5,0xa1,0xa5,0xa3,0xa5,0xa5,0xa5,0xa7,0xa5,0xa9,0x0d,0x0a}, + {14,0x31,0x20,0x8e,0xa7,0x8e,0xa8,0x8e,0xa9,0x8e,0xaa,0x8e,0xab,0x0d,0x0a}, + {14,0x31,0x20,0xa1,0xd6,0xc6,0xfc,0xcb,0xdc,0xb8,0xec,0xa1,0xd7,0x0d,0x0a}, + {10,0x31,0x20,0xa1,0xfe,0xa1,0xfe,0xa2,0xa9,0x0d,0x0a}, + {14,0x31,0x20,0xa2,0xa8,0xa1,0xda,0x74,0x65,0x73,0x74,0xa1,0xdb,0x0d,0x0a} + }; + + INT srcsz, destsz; + INT i; + HRESULT hr; + CHAR output[30]; + WCHAR outputW[30]; + int outlen; + + /* test unc->jis */ + for (i = 0; i < 9; i++) + { + int j; + destsz = 30; + outlen = jis_jp[i][0]; + srcsz = unc_jp[i][0]; + hr = pConvertINetUnicodeToMultiByte(NULL, 50220, &unc_jp[i][1], &srcsz, output, &destsz); + ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n", i, hr); + ok(destsz == outlen, "(%i) Expected %i, got %i\n",i,outlen,destsz); + ok(srcsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],srcsz); + ok(memcmp(output,&jis_jp[i][1],destsz)==0,"(%i) Strings do not match\n",i); + + /* and back */ + srcsz = outlen; + destsz = 30; + hr = pConvertINetMultiByteToUnicode(NULL, 50220, output, &srcsz, outputW,&destsz); + + /* + * JIS does not have hankata so it get automatically converted to + * zenkata. this means that strings 1 and 2 are identical as well as + * strings 4 and 5. + */ + j = i; + if (i == 2) j = 1; + if (i == 5) j = 4; + + ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n",i, hr); + ok(destsz == unc_jp[j][0],"(%i) Expected %i, got %i\n",i,unc_jp[j][0],destsz); + ok(srcsz == outlen,"(%i) Expected %i, got %i\n",i,outlen,srcsz); + ok(memcmp(outputW,&unc_jp[j][1],destsz)==0,"(%i) Strings do not match\n",i); + } + + /* test unc->sjis */ + for (i = 0; i < 9; i++) + { + destsz = 30; + outlen = sjis_jp[i][0]; + srcsz = unc_jp[i][0]; + + hr = pConvertINetUnicodeToMultiByte(NULL, 932, &unc_jp[i][1], &srcsz, output, &destsz); + ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n",i,hr); + ok(destsz == outlen,"(%i) Expected %i, got %i\n",i,outlen,destsz); + ok(srcsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],srcsz); + ok(memcmp(output,&sjis_jp[i][1],outlen)==0,"(%i) Strings do not match\n",i); + + srcsz = outlen; + destsz = 30; + hr = pConvertINetMultiByteToUnicode(NULL, 932, output, &srcsz, outputW,&destsz); + + ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n", i, hr); + ok(destsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],destsz); + ok(srcsz == outlen,"(%i) Expected %i, got %i\n",i,outlen,srcsz); + ok(memcmp(outputW,&unc_jp[i][1],destsz)==0,"(%i) Strings do not match\n",i); + } + + /* test unc->euc */ + for (i = 0; i < 9; i++) + { + destsz = 30; + outlen = euc_jp[i][0]; + srcsz = unc_jp[i][0]; + + hr = pConvertINetUnicodeToMultiByte(NULL, 51932, &unc_jp[i][1], &srcsz, output, &destsz); + ok(hr == S_OK, "(%i) Expected S_OK, got %08x\n",i,hr); + ok(destsz == outlen, "(%i) Expected %i, got %i\n",i,outlen,destsz); + ok(srcsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],destsz); + ok(memcmp(output,&euc_jp[i][1],outlen)==0,"(%i) Strings do not match\n",i); + + srcsz = outlen; + destsz = 30; + hr = pConvertINetMultiByteToUnicode(NULL, 51932, output, &srcsz, outputW,&destsz); + + ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n",i,hr); + ok(destsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],destsz); + ok(srcsz == outlen,"(%i) Expected %i, got %i\n",i,outlen,srcsz); + ok(memcmp(outputW,&unc_jp[i][1],destsz)==0,"(%i) Strings do not match\n",i); + } + + /* Japanese autodetect */ + i = 0; + destsz = 30; + srcsz = jis_jp[i][0]; + hr = pConvertINetMultiByteToUnicode(NULL, 50932, &jis_jp[i][1], &srcsz, outputW, &destsz); + ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n",i,hr); + ok(destsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],destsz); + ok(srcsz == jis_jp[i][0],"(%i) Expected %i, got %i\n",i,jis_jp[i][0],srcsz); + ok(memcmp(outputW,&unc_jp[i][1],destsz)==0,"(%i) Strings do not match\n",i); + + i = 1; + destsz = 30; + srcsz = sjis_jp[i][0]; + hr = pConvertINetMultiByteToUnicode(NULL, 50932, &sjis_jp[i][1], &srcsz, outputW, &destsz); + ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n",i,hr); + ok(destsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],destsz); + ok(srcsz == sjis_jp[i][0],"(%i) Expected %i, got %i\n",i,sjis_jp[i][0],srcsz); + ok(memcmp(outputW,&unc_jp[i][1],destsz)==0,"(%i) Strings do not match\n",i); + + i = 2; + destsz = 30; + srcsz = euc_jp[i][0]; + hr = pConvertINetMultiByteToUnicode(NULL, 50932, &euc_jp[i][1], &srcsz, outputW, &destsz); ok(hr == S_OK,"(%i) Expected S_OK, got %08x\n",i,hr); + ok(destsz == unc_jp[i][0],"(%i) Expected %i, got %i\n",i,unc_jp[i][0],destsz); + ok(srcsz == euc_jp[i][0],"(%i) Expected %i, got %i\n",i,euc_jp[i][0],srcsz); + ok(memcmp(outputW,&unc_jp[i][1],destsz)==0,"(%i) Strings do not match\n",i); +} + START_TEST(mlang) { IMultiLanguage2 *iML2 = NULL; @@ -1158,6 +1329,8 @@ START_TEST(mlang) test_ConvertINetUnicodeToMultiByte(); + test_JapaneseConversion(); + ret = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, &IID_IMLangFontLink, (void **)&iMLFL); diff --git a/dlls/mscoree/mscoree.spec b/dlls/mscoree/mscoree.spec index 0a75722f7c5..0195b621df8 100644 --- a/dlls/mscoree/mscoree.spec +++ b/dlls/mscoree/mscoree.spec @@ -80,7 +80,7 @@ @ stdcall ND_RU1(ptr long) @ stdcall ND_WI2(ptr long long) @ stdcall ND_WI4(ptr long long) -@ stdcall ND_WI8(ptr long long long) +@ stdcall ND_WI8(ptr long double) @ stdcall ND_WU1(ptr long long) @ stub OpenCtrs @ stub ReOpenMetaDataWithMemoryEx diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 670c6151957..244661f9179 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -745,8 +745,27 @@ static HRESULT WINAPI HTMLElement_get_offsetWidth(IHTMLElement *iface, long *p) static HRESULT WINAPI HTMLElement_get_offsetHeight(IHTMLElement *iface, long *p) { HTMLElement *This = HTMLELEM_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsIDOMNSHTMLElement *nselem; + PRInt32 offset = 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_GetOffsetHeight(nselem, &offset); + nsIDOMNSHTMLElement_Release(nselem); + if(NS_FAILED(nsres)) { + ERR("GetOffsetHeight failed: %08x\n", nsres); + return E_FAIL; + } + + *p = offset; + return S_OK; } static HRESULT WINAPI HTMLElement_get_offsetParent(IHTMLElement *iface, IHTMLElement **p) diff --git a/dlls/mshtml/htmlelem2.c b/dlls/mshtml/htmlelem2.c index 5d0443ed68e..3455517d316 100644 --- a/dlls/mshtml/htmlelem2.c +++ b/dlls/mshtml/htmlelem2.c @@ -713,15 +713,51 @@ static HRESULT WINAPI HTMLElement2_createControlRange(IHTMLElement2 *iface, IDis static HRESULT WINAPI HTMLElement2_get_scrollHeight(IHTMLElement2 *iface, long *p) { HTMLElement *This = HTMLELEM2_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsIDOMNSHTMLElement *nselem; + PRInt32 height = 0; + nsresult nsres; + + TRACE("(%p)->(%p)\n", This, p); + + nsres = nsIDOMElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem); + if(NS_SUCCEEDED(nsres)) { + nsres = nsIDOMNSHTMLElement_GetScrollHeight(nselem, &height); + nsIDOMNSHTMLElement_Release(nselem); + if(NS_FAILED(nsres)) + ERR("GetScrollHeight failed: %08x\n", nsres); + }else { + ERR("Could not get nsIDOMNSHTMLElement interface: %08x\n", nsres); + } + + *p = height; + TRACE("*p = %ld\n", *p); + + return S_OK; } static HRESULT WINAPI HTMLElement2_get_scrollWidth(IHTMLElement2 *iface, long *p) { HTMLElement *This = HTMLELEM2_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + nsIDOMNSHTMLElement *nselem; + PRInt32 width = 0; + nsresult nsres; + + TRACE("(%p)->(%p)\n", This, p); + + nsres = nsIDOMElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem); + if(NS_SUCCEEDED(nsres)) { + nsres = nsIDOMNSHTMLElement_GetScrollWidth(nselem, &width); + nsIDOMNSHTMLElement_Release(nselem); + if(NS_FAILED(nsres)) + ERR("GetScrollWidth failed: %08x\n", nsres); + }else { + ERR("Could not get nsIDOMNSHTMLElement interface: %08x\n", nsres); + } + + *p = width; + TRACE("*p = %ld\n", *p); + + return S_OK; } static HRESULT WINAPI HTMLElement2_put_scrollTop(IHTMLElement2 *iface, long v) @@ -751,8 +787,26 @@ static HRESULT WINAPI HTMLElement2_put_scrollTop(IHTMLElement2 *iface, long v) static HRESULT WINAPI HTMLElement2_get_scrollTop(IHTMLElement2 *iface, long *p) { HTMLElement *This = HTMLELEM2_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 = nsIDOMElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem); + if(NS_SUCCEEDED(nsres)) { + nsres = nsIDOMNSHTMLElement_GetScrollTop(nselem, &top); + nsIDOMNSHTMLElement_Release(nselem); + if(NS_FAILED(nsres)) + ERR("GetScrollTop failed: %08x\n", nsres); + }else { + ERR("Could not get nsIDOMNSHTMLElement interface: %08x\n", nsres); + } + + *p = top; + TRACE("*p = %ld\n", *p); + + return S_OK; } static HRESULT WINAPI HTMLElement2_put_scrollLeft(IHTMLElement2 *iface, long v) diff --git a/dlls/mshtml/htmltextcont.c b/dlls/mshtml/htmltextcont.c index f6f7c8ba192..212784cf4d0 100644 --- a/dlls/mshtml/htmltextcont.c +++ b/dlls/mshtml/htmltextcont.c @@ -101,47 +101,19 @@ static HRESULT WINAPI HTMLTextContainer_createControlRange(IHTMLTextContainer *i static HRESULT WINAPI HTMLTextContainer_get_scrollHeight(IHTMLTextContainer *iface, long *p) { HTMLTextContainer *This = HTMLTEXTCONT_THIS(iface); - nsIDOMNSHTMLElement *nselem; - PRInt32 height = 0; - nsresult nsres; TRACE("(%p)->(%p)\n", This, p); - nsres = nsIDOMElement_QueryInterface(This->element.nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem); - if(NS_SUCCEEDED(nsres)) { - nsIDOMNSHTMLElement_GetScrollHeight(nselem, &height); - nsIDOMNSHTMLElement_Release(nselem); - }else { - ERR("Could not get nsIDOMNSHTMLElement interface: %08x\n", nsres); - } - - *p = height; - TRACE("*p = %ld\n", *p); - - return S_OK; + return IHTMLElement2_get_scrollHeight(HTMLELEM2(&This->element), p); } static HRESULT WINAPI HTMLTextContainer_get_scrollWidth(IHTMLTextContainer *iface, long *p) { HTMLTextContainer *This = HTMLTEXTCONT_THIS(iface); - nsIDOMNSHTMLElement *nselem; - PRInt32 width = 0; - nsresult nsres; TRACE("(%p)->(%p)\n", This, p); - nsres = nsIDOMElement_QueryInterface(This->element.nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem); - if(NS_SUCCEEDED(nsres)) { - nsIDOMNSHTMLElement_GetScrollWidth(nselem, &width); - nsIDOMNSHTMLElement_Release(nselem); - }else { - ERR("Could not get nsIDOMNSHTMLElement interface: %08x\n", nsres); - } - - *p = width; - TRACE("*p = %ld\n", *p); - - return S_OK; + return IHTMLElement2_get_scrollWidth(HTMLELEM2(&This->element), p); } static HRESULT WINAPI HTMLTextContainer_put_scrollTop(IHTMLTextContainer *iface, long v) @@ -156,8 +128,10 @@ static HRESULT WINAPI HTMLTextContainer_put_scrollTop(IHTMLTextContainer *iface, static HRESULT WINAPI HTMLTextContainer_get_scrollTop(IHTMLTextContainer *iface, long *p) { HTMLTextContainer *This = HTMLTEXTCONT_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, p); + + return IHTMLElement2_get_scrollTop(HTMLELEM2(&This->element), p); } static HRESULT WINAPI HTMLTextContainer_put_scrollLeft(IHTMLTextContainer *iface, long v) diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index 9c285b070da..32bd9bf7493 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -237,8 +237,13 @@ static HRESULT WINAPI OmNavigator_get_userLanguage(IOmNavigator *iface, BSTR *p) static HRESULT WINAPI OmNavigator_get_platform(IOmNavigator *iface, BSTR *p) { OmNavigator *This = OMNAVIGATOR_THIS(iface); - FIXME("(%p)->(%p)\n", This, p); - return E_NOTIMPL; + + static const WCHAR win32W[] = {'W','i','n','3','2',0}; + + TRACE("(%p)->(%p)\n", This, p); + + *p = SysAllocString(win32W); + return S_OK; } static HRESULT WINAPI OmNavigator_get_appMinorVersion(IOmNavigator *iface, BSTR *p) diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index cb15187c9e6..e7a2907b12f 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -496,6 +496,9 @@ static void _test_elem_offset(unsigned line, IUnknown *unk) hres = IHTMLElement_get_offsetTop(elem, &l); ok_(__FILE__,line) (hres == S_OK, "get_offsetTop failed: %08x\n", hres); + hres = IHTMLElement_get_offsetHeight(elem, &l); + ok_(__FILE__,line) (hres == S_OK, "get_offsetHeight failed: %08x\n", hres); + IHTMLElement_Release(elem); } @@ -968,6 +971,75 @@ static long _get_node_type(unsigned line, IUnknown *unk) return type; } +#define elem_get_scroll_height(u) _elem_get_scroll_height(__LINE__,u) +static long _elem_get_scroll_height(unsigned line, IUnknown *unk) +{ + IHTMLElement2 *elem = _get_elem2_iface(line, unk); + IHTMLTextContainer *txtcont; + long l = -1, l2 = -1; + HRESULT hres; + + hres = IHTMLElement2_get_scrollHeight(elem, &l); + ok_(__FILE__,line) (hres == S_OK, "get_scrollHeight failed: %08x\n", hres); + IHTMLElement2_Release(elem); + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLTextContainer, (void**)&txtcont); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLTextContainer: %08x\n", hres); + + hres = IHTMLTextContainer_get_scrollHeight(txtcont, &l2); + IHTMLTextContainer_Release(txtcont); + ok_(__FILE__,line) (hres == S_OK, "IHTMLTextContainer::get_scrollHeight failed: %ld\n", l2); + ok_(__FILE__,line) (l == l2, "unexpected height %ld, expected %ld\n", l2, l); + + return l; +} + +#define elem_get_scroll_width(u) _elem_get_scroll_width(__LINE__,u) +static long _elem_get_scroll_width(unsigned line, IUnknown *unk) +{ + IHTMLElement2 *elem = _get_elem2_iface(line, unk); + IHTMLTextContainer *txtcont; + long l = -1, l2 = -1; + HRESULT hres; + + hres = IHTMLElement2_get_scrollWidth(elem, &l); + ok_(__FILE__,line) (hres == S_OK, "get_scrollWidth failed: %08x\n", hres); + IHTMLElement2_Release(elem); + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLTextContainer, (void**)&txtcont); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLTextContainer: %08x\n", hres); + + hres = IHTMLTextContainer_get_scrollWidth(txtcont, &l2); + IHTMLTextContainer_Release(txtcont); + ok_(__FILE__,line) (hres == S_OK, "IHTMLTextContainer::get_scrollWidth failed: %ld\n", l2); + ok_(__FILE__,line) (l == l2, "unexpected width %ld, expected %ld\n", l2, l); + + return l; +} + +#define elem_get_scroll_top(u) _elem_get_scroll_top(__LINE__,u) +static long _elem_get_scroll_top(unsigned line, IUnknown *unk) +{ + IHTMLElement2 *elem = _get_elem2_iface(line, unk); + IHTMLTextContainer *txtcont; + long l = -1, l2 = -1; + HRESULT hres; + + hres = IHTMLElement2_get_scrollTop(elem, &l); + ok_(__FILE__,line) (hres == S_OK, "get_scrollTop failed: %08x\n", hres); + IHTMLElement2_Release(elem); + + hres = IUnknown_QueryInterface(unk, &IID_IHTMLTextContainer, (void**)&txtcont); + ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLTextContainer: %08x\n", hres); + + hres = IHTMLTextContainer_get_scrollTop(txtcont, &l2); + IHTMLTextContainer_Release(txtcont); + ok_(__FILE__,line) (hres == S_OK, "IHTMLTextContainer::get_scrollTop failed: %ld\n", l2); + ok_(__FILE__,line) (l == l2, "unexpected top %ld, expected %ld\n", l2, l); + + return l; +} + #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) { @@ -1822,6 +1894,12 @@ static void test_navigator(IHTMLDocument2 *doc) ok(!strcmp_wa(bstr, "Mozilla"), "Unexpected appCodeName %s\n", dbgstr_w(bstr)); SysFreeString(bstr); + bstr = NULL; + hres = IOmNavigator_get_platform(navigator, &bstr); + ok(hres == S_OK, "get_appMinorVersion failed: %08x\n", hres); + ok(!strcmp_wa(bstr, "Win32"), "unexpected platform %s\n", dbgstr_w(bstr)); + SysFreeString(bstr); + ref = IOmNavigator_Release(navigator); ok(!ref, "navigator should be destroyed here\n"); } @@ -1927,6 +2005,7 @@ static void test_default_selection(IHTMLDocument2 *doc) static void test_default_body(IHTMLBodyElement *body) { + long l; BSTR bstr; HRESULT hres; @@ -1934,6 +2013,13 @@ static void test_default_body(IHTMLBodyElement *body) hres = IHTMLBodyElement_get_background(body, &bstr); ok(hres == S_OK, "get_background failed: %08x\n", hres); ok(bstr == NULL, "bstr != NULL\n"); + + l = elem_get_scroll_height((IUnknown*)body); + ok(l != -1, "scrollHeight == -1\n"); + l = elem_get_scroll_width((IUnknown*)body); + ok(l != -1, "scrollWidth == -1\n"); + l = elem_get_scroll_top((IUnknown*)body); + ok(!l, "scrollWidth = %ld\n", l); } static void test_window(IHTMLDocument2 *doc) diff --git a/dlls/mshtml/tests/protocol.c b/dlls/mshtml/tests/protocol.c index 4e8b3d0c79a..b17028f992d 100644 --- a/dlls/mshtml/tests/protocol.c +++ b/dlls/mshtml/tests/protocol.c @@ -266,9 +266,13 @@ static void res_sec_url_cmp(LPCWSTR url, DWORD size, LPCWSTR file) return; } + SetLastError(0xdeadbeef); len = SearchPathW(NULL, file, NULL, sizeof(buf)/sizeof(WCHAR), buf, NULL); if(!len) { - ok(0, "SearchPath failed: %u\n", GetLastError()); + if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + win_skip("SearchPathW is not implemented\n"); + else + ok(0, "SearchPath failed: %u\n", GetLastError()); return; } diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 5bb7008174c..6662945bccc 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -2994,7 +2994,10 @@ static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param) MSICOMPONENT *comp; MSIFILE *file; typelib_struct tl_struct; + ITypeLib *tlib; HMODULE module; + HRESULT hr; + static const WCHAR szTYPELIB[] = {'T','Y','P','E','L','I','B',0}; component = MSI_RecordGetString(row,3); @@ -3063,7 +3066,16 @@ static UINT ITERATE_RegisterTypeLibraries(MSIRECORD *row, LPVOID param) msi_free(tl_struct.source); } else - ERR("Could not load file! %s\n", debugstr_w(file->TargetPath)); + { + hr = LoadTypeLibEx(file->TargetPath, REGKIND_REGISTER, &tlib); + if (FAILED(hr)) + { + ERR("Failed to load type library: %08x\n", hr); + return ERROR_FUNCTION_FAILED; + } + + ITypeLib_Release(tlib); + } return ERROR_SUCCESS; } @@ -4229,11 +4241,20 @@ static UINT msi_unpublish_product(MSIPACKAGE *package) goto done; MSIREG_DeleteProductKey(package->ProductCode); - MSIREG_DeleteUserProductKey(package->ProductCode); MSIREG_DeleteUserDataProductKey(package->ProductCode); - MSIREG_DeleteUserFeaturesKey(package->ProductCode); MSIREG_DeleteUninstallKey(package->ProductCode); + if (package->Context == MSIINSTALLCONTEXT_MACHINE) + { + MSIREG_DeleteLocalClassesProductKey(package->ProductCode); + MSIREG_DeleteLocalClassesFeaturesKey(package->ProductCode); + } + else + { + MSIREG_DeleteUserProductKey(package->ProductCode); + MSIREG_DeleteUserFeaturesKey(package->ProductCode); + } + upgrade = msi_dup_property(package, szUpgradeCode); if (upgrade) { diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index 0bd23fac949..c5dd57da07e 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -45,6 +45,27 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi); static const WCHAR installerW[] = {'\\','I','n','s','t','a','l','l','e','r',0}; +static UINT msi_locate_product(LPCWSTR szProduct, MSIINSTALLCONTEXT *context) +{ + HKEY hkey = NULL; + + *context = MSIINSTALLCONTEXT_NONE; + + if (MSIREG_OpenLocalManagedProductKey(szProduct, &hkey, FALSE) == ERROR_SUCCESS) + *context = MSIINSTALLCONTEXT_USERMANAGED; + else if (MSIREG_OpenLocalClassesProductKey(szProduct, &hkey, FALSE) == ERROR_SUCCESS) + *context = MSIINSTALLCONTEXT_MACHINE; + else if (MSIREG_OpenUserProductsKey(szProduct, &hkey, FALSE) == ERROR_SUCCESS) + *context = MSIINSTALLCONTEXT_USERUNMANAGED; + + RegCloseKey(hkey); + + if (*context == MSIINSTALLCONTEXT_NONE) + return ERROR_UNKNOWN_PRODUCT; + + return ERROR_SUCCESS; +} + UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct) { UINT r; @@ -66,69 +87,78 @@ UINT WINAPI MsiOpenProductA(LPCSTR szProduct, MSIHANDLE *phProduct) return r; } -static UINT MSI_OpenProductW( LPCWSTR szProduct, MSIPACKAGE **ppackage ) +static UINT MSI_OpenProductW(LPCWSTR szProduct, MSIPACKAGE **package) { - LPWSTR path = NULL; UINT r; - HKEY hKeyProduct = NULL; - DWORD count, type; + HKEY props; + LPWSTR path; + MSIINSTALLCONTEXT context; - TRACE("%s %p\n", debugstr_w(szProduct), ppackage ); + static const WCHAR managed[] = { + 'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0}; + static const WCHAR local[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0}; - r = MSIREG_OpenUninstallKey(szProduct,&hKeyProduct,FALSE); - if( r != ERROR_SUCCESS ) - { - r = ERROR_UNKNOWN_PRODUCT; - goto end; - } + TRACE("%s %p\n", debugstr_w(szProduct), package); - /* find the size of the path */ - type = count = 0; - r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW, - NULL, &type, NULL, &count ); - if( r != ERROR_SUCCESS ) - { - r = ERROR_UNKNOWN_PRODUCT; - goto end; - } + r = msi_locate_product(szProduct, &context); + if (r != ERROR_SUCCESS) + return r; - /* now alloc and fetch the path of the database to open */ - path = msi_alloc( count ); - if( !path ) - goto end; + if (context == MSIINSTALLCONTEXT_MACHINE) + r = MSIREG_OpenLocalSystemInstallProps(szProduct, &props, FALSE); + else if (context == MSIINSTALLCONTEXT_USERMANAGED || + context == MSIINSTALLCONTEXT_USERUNMANAGED) + r = MSIREG_OpenCurrentUserInstallProps(szProduct, &props, FALSE); + + if (r != ERROR_SUCCESS) + return ERROR_UNKNOWN_PRODUCT; + + if (context == MSIINSTALLCONTEXT_USERMANAGED) + path = msi_reg_get_val_str(props, managed); + else + path = msi_reg_get_val_str(props, local); + + r = ERROR_UNKNOWN_PRODUCT; + + if (!path || GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES) + goto done; - r = RegQueryValueExW( hKeyProduct, INSTALLPROPERTY_LOCALPACKAGEW, - NULL, &type, (LPBYTE) path, &count ); - if( r != ERROR_SUCCESS ) + if (PathIsRelativeW(path)) { - r = ERROR_UNKNOWN_PRODUCT; - goto end; + r = ERROR_INSTALL_PACKAGE_OPEN_FAILED; + goto done; } - r = MSI_OpenPackageW( path, ppackage ); - -end: - msi_free( path ); - if( hKeyProduct ) - RegCloseKey( hKeyProduct ); + r = MSI_OpenPackageW(path, package); +done: + RegCloseKey(props); + msi_free(path); return r; } -UINT WINAPI MsiOpenProductW( LPCWSTR szProduct, MSIHANDLE *phProduct ) +UINT WINAPI MsiOpenProductW(LPCWSTR szProduct, MSIHANDLE *phProduct) { - MSIPACKAGE *package = NULL; - UINT r; + MSIPACKAGE *package = NULL; + WCHAR squished_pc[GUID_SIZE]; + UINT r; + + if (!szProduct || !squash_guid(szProduct, squished_pc)) + return ERROR_INVALID_PARAMETER; - r = MSI_OpenProductW( szProduct, &package ); - if( r == ERROR_SUCCESS ) - { - *phProduct = alloc_msihandle( &package->hdr ); - if (! *phProduct) - r = ERROR_NOT_ENOUGH_MEMORY; - msiobj_release( &package->hdr ); - } - return r; + if (!phProduct) + return ERROR_INVALID_PARAMETER; + + r = MSI_OpenProductW(szProduct, &package); + if (r != ERROR_SUCCESS) + return r; + + *phProduct = alloc_msihandle(&package->hdr); + if (!*phProduct) + r = ERROR_NOT_ENOUGH_MEMORY; + + msiobj_release(&package->hdr); + return r; } UINT WINAPI MsiAdvertiseProductA(LPCSTR szPackagePath, LPCSTR szScriptfilePath, @@ -346,43 +376,47 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState, LPCWSTR szCommandLine) { MSIPACKAGE* package = NULL; + MSIINSTALLCONTEXT context; UINT r; DWORD sz; WCHAR sourcepath[MAX_PATH]; WCHAR filename[MAX_PATH]; + LPWSTR commandline; + static const WCHAR szInstalled[] = { ' ','I','n','s','t','a','l','l','e','d','=','1',0}; - LPWSTR commandline; + static const WCHAR szRemoveAll[] = { + ' ','R','E','M','O','V','E','=','A','L','L',0}; + static const WCHAR szMachine[] = { + ' ','A','L','L','U','S','E','R','S','=','1',0}; TRACE("%s %d %d %s\n",debugstr_w(szProduct), iInstallLevel, eInstallState, debugstr_w(szCommandLine)); - if (eInstallState != INSTALLSTATE_LOCAL && - eInstallState != INSTALLSTATE_DEFAULT) + if (!szProduct || lstrlenW(szProduct) != GUID_SIZE - 1) + return ERROR_INVALID_PARAMETER; + + if (eInstallState == INSTALLSTATE_ADVERTISED || + eInstallState == INSTALLSTATE_SOURCE) { - FIXME("Not implemented for anything other than local installs\n"); + FIXME("State %d not implemented\n", eInstallState); return ERROR_CALL_NOT_IMPLEMENTED; } + r = msi_locate_product(szProduct, &context); + if (r != ERROR_SUCCESS) + return r; + sz = sizeof(sourcepath); - MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, - MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, - &sz); + MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT, + INSTALLPROPERTY_LASTUSEDSOURCEW, sourcepath, &sz); sz = sizeof(filename); - MsiSourceListGetInfoW(szProduct, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, - MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); + MsiSourceListGetInfoW(szProduct, NULL, context, MSICODE_PRODUCT, + INSTALLPROPERTY_PACKAGENAMEW, filename, &sz); - lstrcatW(sourcepath,filename); - - /* - * ok 1, we need to find the msi file for this product. - * 2, find the source dir for the files - * 3, do the configure/install. - * 4, cleanupany runonce entry. - */ - - r = MSI_OpenProductW( szProduct, &package ); + lstrcatW(sourcepath, filename); + r = MSI_OpenPackageW(sourcepath, &package); if (r != ERROR_SUCCESS) return r; @@ -391,8 +425,14 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, if (szCommandLine) sz += lstrlenW(szCommandLine); + if (eInstallState == INSTALLSTATE_ABSENT) + sz += lstrlenW(szRemoveAll); + + if (context == MSIINSTALLCONTEXT_MACHINE) + sz += lstrlenW(szMachine); + commandline = msi_alloc(sz * sizeof(WCHAR)); - if (!commandline ) + if (!commandline) { r = ERROR_OUTOFMEMORY; goto end; @@ -405,6 +445,12 @@ UINT WINAPI MsiConfigureProductExW(LPCWSTR szProduct, int iInstallLevel, if (MsiQueryProductStateW(szProduct) != INSTALLSTATE_UNKNOWN) lstrcatW(commandline,szInstalled); + if (eInstallState == INSTALLSTATE_ABSENT) + lstrcatW(commandline, szRemoveAll); + + if (context == MSIINSTALLCONTEXT_MACHINE) + lstrcatW(commandline, szMachine); + r = MSI_InstallPackage( package, sourcepath, commandline ); msi_free(commandline); diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 19abc3f4b7e..05df705d413 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -790,6 +790,8 @@ 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 UINT MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode); +extern UINT MSIREG_DeleteLocalClassesFeaturesKey(LPCWSTR szProductCode); 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 a12a825f343..9a4837b9e24 100644 --- a/dlls/msi/registry.c +++ b/dlls/msi/registry.c @@ -1088,6 +1088,23 @@ UINT MSIREG_OpenLocalClassesProductKey(LPCWSTR szProductCode, HKEY *key, BOOL cr return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); } +UINT MSIREG_DeleteLocalClassesProductKey(LPCWSTR szProductCode) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n", debugstr_w(szProductCode)); + + if (!squash_guid(szProductCode, squished_pc)) + return ERROR_FUNCTION_FAILED; + + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath, szInstaller_LocalClassesProd_fmt, squished_pc); + + return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath); +} + UINT MSIREG_OpenLocalClassesFeaturesKey(LPCWSTR szProductCode, HKEY *key, BOOL create) { WCHAR squished_pc[GUID_SIZE]; @@ -1108,6 +1125,23 @@ UINT MSIREG_OpenLocalClassesFeaturesKey(LPCWSTR szProductCode, HKEY *key, BOOL c return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); } +UINT MSIREG_DeleteLocalClassesFeaturesKey(LPCWSTR szProductCode) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n", debugstr_w(szProductCode)); + + if (!squash_guid(szProductCode, squished_pc)) + return ERROR_FUNCTION_FAILED; + + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath, szInstaller_LocalClassesFeat_fmt, squished_pc); + + return RegDeleteTreeW(HKEY_LOCAL_MACHINE, keypath); +} + UINT MSIREG_OpenLocalManagedProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create) { WCHAR squished_pc[GUID_SIZE]; diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 4748831365d..6e91adc441d 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -705,6 +705,27 @@ static const CHAR sp_directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\ "ONEDIR\tMSITESTDIR\t.:shortone|longone\n" "TWODIR\tONEDIR\t.:shorttwo|longtwo"; +static const CHAR mcp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" + "s72\tS38\ts72\ti2\tS255\tS72\n" + "Component\tComponent\n" + "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n" + "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n" + "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n"; + +static const CHAR mcp_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n" + "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n" + "Feature\tFeature\n" + "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n" + "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n" + "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0"; + +static const CHAR mcp_feature_comp_dat[] = "Feature_\tComponent_\n" + "s38\ts72\n" + "FeatureComponents\tFeature_\tComponent_\n" + "hydroxyl\thydrogen\n" + "heliox\thelium\n" + "lithia\tlithium"; + typedef struct _msi_table { const CHAR *filename; @@ -1067,6 +1088,18 @@ static const msi_table sp_tables[] = ADD_TABLE(property), }; +static const msi_table mcp_tables[] = +{ + ADD_TABLE(mcp_component), + ADD_TABLE(directory), + ADD_TABLE(mcp_feature), + ADD_TABLE(mcp_feature_comp), + ADD_TABLE(rem_file), + ADD_TABLE(rem_install_exec_seq), + ADD_TABLE(rof_media), + ADD_TABLE(property), +}; + /* cabinet definitions */ /* make the max size large so there is only one cab file */ @@ -4951,6 +4984,128 @@ static void test_sourcepath(void) DeleteFileA(msifile); } +static void test_MsiConfigureProductEx(void) +{ + UINT r; + + CreateDirectoryA("msitest", NULL); + create_file("msitest\\hydrogen", 500); + create_file("msitest\\helium", 500); + create_file("msitest\\lithium", 500); + + create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + /* NULL szProduct */ + r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT, + INSTALLSTATE_DEFAULT, "PROPVAR=42"); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + + /* empty szProduct */ + r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT, + INSTALLSTATE_DEFAULT, "PROPVAR=42"); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + + /* garbage szProduct */ + r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT, + INSTALLSTATE_DEFAULT, "PROPVAR=42"); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + + /* guid without brackets */ + r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + + /* guid with brackets */ + r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + + /* same length as guid, but random */ + r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + + /* product not installed yet */ + r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + + /* install the product, per-user unmanaged */ + r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + /* product is installed per-user managed, remove it */ + r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine + { + ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest", FALSE), "File not removed\n"); + } + + /* product has been removed */ + r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); + + /* install the product, machine */ + r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(pf_exists("msitest\\hydrogen"), "File not installed\n"); + ok(pf_exists("msitest\\helium"), "File not installed\n"); + ok(pf_exists("msitest\\lithium"), "File not installed\n"); + ok(pf_exists("msitest"), "File not installed\n"); + + /* product is installed machine, remove it */ + r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT, + "PROPVAR=42"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine + { + ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n"); + ok(!delete_pf("msitest", FALSE), "File not removed\n"); + } + + /* product has been removed */ + r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", + INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, + "PROPVAR=42"); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r); + + DeleteFileA(msifile); + DeleteFileA("msitest\\hydrogen"); + DeleteFileA("msitest\\helium"); + DeleteFileA("msitest\\lithium"); + RemoveDirectoryA("msitest"); +} + START_TEST(install) { DWORD len; @@ -5003,6 +5158,7 @@ START_TEST(install) test_customaction51(); test_installstate(); test_sourcepath(); + test_MsiConfigureProductEx(); SetCurrentDirectoryA(prev_path); } diff --git a/dlls/msi/tests/msi.c b/dlls/msi/tests/msi.c index 52cfd74564e..0e262ae78c0 100644 --- a/dlls/msi/tests/msi.c +++ b/dlls/msi/tests/msi.c @@ -24,10 +24,13 @@ #include #include #include +#include #include #include "wine/test.h" +static const char msifile[] = "winetest.msi"; + static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*); static INSTALLSTATE (WINAPI *pMsiGetComponentPathA) @@ -68,6 +71,112 @@ static void init_functionpointers(void) #undef GET_PROC } +static UINT run_query(MSIHANDLE hdb, const char *query) +{ + MSIHANDLE hview = 0; + UINT r; + + r = MsiDatabaseOpenView(hdb, query, &hview); + if (r != ERROR_SUCCESS) + return r; + + r = MsiViewExecute(hview, 0); + if (r == ERROR_SUCCESS) + r = MsiViewClose(hview); + MsiCloseHandle(hview); + return r; +} + +static UINT set_summary_info(MSIHANDLE hdb, LPSTR prodcode) +{ + UINT res; + MSIHANDLE suminfo; + + /* build summary info */ + res = MsiGetSummaryInformation(hdb, NULL, 7, &suminfo); + ok(res == ERROR_SUCCESS, "Failed to open summaryinfo\n"); + + res = MsiSummaryInfoSetProperty(suminfo, 2, VT_LPSTR, 0, NULL, + "Installation Database"); + ok(res == ERROR_SUCCESS, "Failed to set summary info\n"); + + res = MsiSummaryInfoSetProperty(suminfo, 3, VT_LPSTR, 0, NULL, + "Installation Database"); + ok(res == ERROR_SUCCESS, "Failed to set summary info\n"); + + res = MsiSummaryInfoSetProperty(suminfo, 4, VT_LPSTR, 0, NULL, + "Wine Hackers"); + ok(res == ERROR_SUCCESS, "Failed to set summary info\n"); + + res = MsiSummaryInfoSetProperty(suminfo, 7, VT_LPSTR, 0, NULL, + ";1033"); + ok(res == ERROR_SUCCESS, "Failed to set summary info\n"); + + res = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL, + "{A2078D65-94D6-4205-8DEE-F68D6FD622AA}"); + ok(res == ERROR_SUCCESS, "Failed to set summary info\n"); + + res = MsiSummaryInfoSetProperty(suminfo, 14, VT_I4, 100, NULL, NULL); + ok(res == ERROR_SUCCESS, "Failed to set summary info\n"); + + res = MsiSummaryInfoSetProperty(suminfo, 15, VT_I4, 0, NULL, NULL); + ok(res == ERROR_SUCCESS, "Failed to set summary info\n"); + + res = MsiSummaryInfoPersist(suminfo); + ok(res == ERROR_SUCCESS, "Failed to make summary info persist\n"); + + res = MsiCloseHandle(suminfo); + ok(res == ERROR_SUCCESS, "Failed to close suminfo\n"); + + return res; +} + +static MSIHANDLE create_package_db(LPSTR prodcode) +{ + MSIHANDLE hdb = 0; + CHAR query[MAX_PATH]; + UINT res; + + DeleteFile(msifile); + + /* create an empty database */ + res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb); + ok( res == ERROR_SUCCESS , "Failed to create database\n" ); + if (res != ERROR_SUCCESS) + return hdb; + + res = MsiDatabaseCommit(hdb); + ok(res == ERROR_SUCCESS, "Failed to commit database\n"); + + set_summary_info(hdb, prodcode); + + res = run_query(hdb, + "CREATE TABLE `Directory` ( " + "`Directory` CHAR(255) NOT NULL, " + "`Directory_Parent` CHAR(255), " + "`DefaultDir` CHAR(255) NOT NULL " + "PRIMARY KEY `Directory`)"); + ok(res == ERROR_SUCCESS , "Failed to create directory table\n"); + + res = run_query(hdb, + "CREATE TABLE `Property` ( " + "`Property` CHAR(72) NOT NULL, " + "`Value` CHAR(255) " + "PRIMARY KEY `Property`)"); + ok(res == ERROR_SUCCESS , "Failed to create directory table\n"); + + sprintf(query, "INSERT INTO `Property` " + "(`Property`, `Value`) " + "VALUES( 'ProductCode', '%s' )", prodcode); + res = run_query(hdb, query); + ok(res == ERROR_SUCCESS , "Failed\n"); + + res = MsiDatabaseCommit(hdb); + ok(res == ERROR_SUCCESS, "Failed to commit database\n"); + + return hdb; +} + static void test_usefeature(void) { INSTALLSTATE r; @@ -6901,6 +7010,315 @@ static void test_MsiGetUserInfo(void) RegCloseKey(prodkey); } +static void test_MsiOpenProduct(void) +{ + MSIHANDLE hprod, hdb; + CHAR val[MAX_PATH]; + CHAR path[MAX_PATH]; + CHAR keypath[MAX_PATH*2]; + CHAR prodcode[MAX_PATH]; + CHAR prod_squashed[MAX_PATH]; + HKEY prodkey, userkey, props; + LPSTR usersid; + DWORD size; + LONG res; + UINT r; + + GetCurrentDirectoryA(MAX_PATH, path); + lstrcatA(path, "\\"); + + create_test_guid(prodcode, prod_squashed); + get_user_sid(&usersid); + + hdb = create_package_db(prodcode); + MsiCloseHandle(hdb); + + /* NULL szProduct */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(NULL, &hprod); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + /* empty szProduct */ + hprod = 0xdeadbeef; + r = MsiOpenProductA("", &hprod); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + /* garbage szProduct */ + hprod = 0xdeadbeef; + r = MsiOpenProductA("garbage", &hprod); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + /* guid without brackets */ + hprod = 0xdeadbeef; + r = MsiOpenProductA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", &hprod); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + /* guid with brackets */ + hprod = 0xdeadbeef; + r = MsiOpenProductA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", &hprod); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + /* same length as guid, but random */ + hprod = 0xdeadbeef; + r = MsiOpenProductA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", &hprod); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + /* hProduct is NULL */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, NULL); + ok(r == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + /* MSIINSTALLCONTEXT_USERMANAGED */ + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\"); + lstrcatA(keypath, "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 */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + 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, &userkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* user product key exists */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + res = RegCreateKeyA(userkey, "InstallProperties", &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* InstallProperties key exists */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + lstrcpyA(val, path); + lstrcatA(val, "\\winetest.msi"); + res = RegSetValueExA(props, "ManagedLocalPackage", 0, REG_SZ, + (const BYTE *)val, lstrlenA(val) + 1); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* ManagedLocalPackage value exists */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n"); + + size = MAX_PATH; + r = MsiGetPropertyA(hprod, "ProductCode", val, &size); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val); + ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size); + + MsiCloseHandle(hprod); + + RegDeleteValueA(props, "ManagedLocalPackage"); + RegDeleteKeyA(props, ""); + RegCloseKey(props); + RegDeleteKeyA(userkey, ""); + RegCloseKey(userkey); + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); + + /* MSIINSTALLCONTEXT_USERUNMANAGED */ + + 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); + + /* unmanaged product key exists */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + 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, &userkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* user product key exists */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + res = RegCreateKeyA(userkey, "InstallProperties", &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* InstallProperties key exists */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + lstrcpyA(val, path); + lstrcatA(val, "\\winetest.msi"); + res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, + (const BYTE *)val, lstrlenA(val) + 1); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* LocalPackage value exists */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n"); + + size = MAX_PATH; + r = MsiGetPropertyA(hprod, "ProductCode", val, &size); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val); + ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size); + + MsiCloseHandle(hprod); + + RegDeleteValueA(props, "LocalPackage"); + RegDeleteKeyA(props, ""); + RegCloseKey(props); + RegDeleteKeyA(userkey, ""); + RegCloseKey(userkey); + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); + + /* MSIINSTALLCONTEXT_MACHINE */ + + 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); + + /* managed product key exists */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\"); + lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &userkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* user product key exists */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + res = RegCreateKeyA(userkey, "InstallProperties", &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* InstallProperties key exists */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + lstrcpyA(val, path); + lstrcatA(val, "\\winetest.msi"); + res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, + (const BYTE *)val, lstrlenA(val) + 1); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* LocalPackage value exists */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n"); + + size = MAX_PATH; + r = MsiGetPropertyA(hprod, "ProductCode", val, &size); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(!lstrcmpA(val, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, val); + ok(size == lstrlenA(prodcode), "Expected %d, got %d\n", lstrlenA(prodcode), size); + + MsiCloseHandle(hprod); + + res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, + (const BYTE *)"winetest.msi", 13); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* LocalPackage has just the package name */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_INSTALL_PACKAGE_OPEN_FAILED, + "Expected ERROR_INSTALL_PACKAGE_OPEN_FAILED, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + lstrcpyA(val, path); + lstrcatA(val, "\\winetest.msi"); + res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, + (const BYTE *)val, lstrlenA(val) + 1); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + DeleteFileA(msifile); + + /* local package does not exist */ + hprod = 0xdeadbeef; + r = MsiOpenProductA(prodcode, &hprod); + ok(r == ERROR_UNKNOWN_PRODUCT, + "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r); + ok(hprod == 0xdeadbeef, "Expected hprod to be unchanged\n"); + + RegDeleteValueA(props, "LocalPackage"); + RegDeleteKeyA(props, ""); + RegCloseKey(props); + RegDeleteKeyA(userkey, ""); + RegCloseKey(userkey); + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); + + DeleteFileA(msifile); +} + START_TEST(msi) { init_functionpointers(); @@ -6924,6 +7342,7 @@ START_TEST(msi) test_MsiGetProductInfo(); test_MsiGetProductInfoEx(); test_MsiGetUserInfo(); + test_MsiOpenProduct(); } test_MsiGetFileVersion(); diff --git a/dlls/mstask/Makefile.in b/dlls/msisip/Makefile.in similarity index 59% copy from dlls/mstask/Makefile.in copy to dlls/msisip/Makefile.in index 2202e227561..13bcfdd07a0 100644 --- a/dlls/mstask/Makefile.in +++ b/dlls/msisip/Makefile.in @@ -2,15 +2,11 @@ TOPSRCDIR = @top_srcdir@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ -MODULE = mstask.dll -IMPORTS = uuid kernel32 +MODULE = msisip.dll +IMPORTS = crypt32 ole32 kernel32 C_SRCS = \ - factory.c \ - mstask_main.c \ - task_scheduler.c - -IDL_I_SRCS = mstask_local.idl + main.c @MAKE_DLL_RULES@ diff --git a/dlls/msisip/main.c b/dlls/msisip/main.c new file mode 100644 index 00000000000..cea0398e91b --- /dev/null +++ b/dlls/msisip/main.c @@ -0,0 +1,250 @@ +/* + * 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 "windef.h" +#include "winbase.h" +#include "wincrypt.h" +#include "mssip.h" +#define COBJMACROS +#include "objbase.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msisip); + +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; +} + +static GUID mySubject = { 0x000c10f1, 0x0000, 0x0000, + { 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }}; + +/*********************************************************************** + * DllRegisterServer (MSISIP.@) + */ +HRESULT WINAPI DllRegisterServer(void) +{ + static WCHAR msisip[] = { 'M','S','I','S','I','P','.','D','L','L',0 }; + static WCHAR getSignedDataMsg[] = { 'M','s','i','S','I','P','G','e','t', + 'S','i','g','n','e','d','D','a','t','a','M','s','g',0 }; + static WCHAR putSignedDataMsg[] = { 'M','s','i','S','I','P','P','u','t', + 'S','i','g','n','e','d','D','a','t','a','M','s','g',0 }; + static WCHAR createIndirectData[] = { 'M','s','i','S','I','P', + 'C','r','e','a','t','e','I','n','d','i','r','e','c','t','D','a','t','a', + 0 }; + static WCHAR verifyIndirectData[] = { 'M','s','i','S','I','P', + 'V','e','r','i','f','y','I','n','d','i','r','e','c','t','D','a','t','a', + 0 }; + static WCHAR removeSignedDataMsg[] = { 'M','s','i','S','I','P','R','e','m', + 'o','v','e','S','i','g','n','e','d','D','a','t','a','M','s','g', 0 }; + static WCHAR isMyTypeOfFile[] = { 'M','s','i','S','I','P', + 'I','s','M','y','T','y','p','e','O','f','F','i','l','e',0 }; + + SIP_ADD_NEWPROVIDER prov; + + memset(&prov, 0, sizeof(prov)); + prov.cbStruct = sizeof(prov); + prov.pwszDLLFileName = msisip; + prov.pgSubject = &mySubject; + prov.pwszGetFuncName = getSignedDataMsg; + prov.pwszPutFuncName = putSignedDataMsg; + prov.pwszCreateFuncName = createIndirectData; + prov.pwszVerifyFuncName = verifyIndirectData; + prov.pwszRemoveFuncName = removeSignedDataMsg; + prov.pwszIsFunctionNameFmt2 = isMyTypeOfFile; + return CryptSIPAddProvider(&prov) ? S_OK : S_FALSE; +} + +/*********************************************************************** + * DllUnregisterServer (MSISIP.@) + */ +HRESULT WINAPI DllUnregisterServer(void) +{ + CryptSIPRemoveProvider(&mySubject); + return S_OK; +} + +/*********************************************************************** + * MsiSIPGetSignedDataMsg (MSISIP.@) + */ +BOOL WINAPI MsiSIPGetSignedDataMsg(SIP_SUBJECTINFO *pSubjectInfo, + DWORD *pdwEncodingType, DWORD dwIndex, DWORD *pcbSignedDataMsg, + BYTE *pbSignedDataMsg) +{ + static const WCHAR digitalSig[] = { 5,'D','i','g','i','t','a','l', + 'S','i','g','n','a','t','u','r','e',0 }; + BOOL ret = FALSE; + IStorage *stg = NULL; + HRESULT r; + IStream *stm = NULL; + BYTE hdr[2], len[sizeof(DWORD)]; + DWORD count, lenBytes, dataBytes; + + TRACE("(%p %p %d %p %p)\n", pSubjectInfo, pdwEncodingType, dwIndex, + pcbSignedDataMsg, pbSignedDataMsg); + + r = StgOpenStorage(pSubjectInfo->pwsFileName, NULL, + STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg); + if (FAILED(r)) + { + TRACE("couldn't open %s\n", debugstr_w(pSubjectInfo->pwsFileName)); + goto end; + } + + r = IStorage_OpenStream(stg, digitalSig, 0, + STGM_READ|STGM_SHARE_EXCLUSIVE, 0, &stm); + if (FAILED(r)) + { + TRACE("couldn't find digital signature stream\n"); + goto freestorage; + } + + r = IStream_Read(stm, hdr, sizeof(hdr), &count); + if (FAILED(r) || count != sizeof(hdr)) + goto freestream; + if (hdr[0] != 0x30) + { + WARN("unexpected data in digital sig: 0x%02x%02x\n", hdr[0], hdr[1]); + goto freestream; + } + + /* Read the asn.1 length from the stream. Only supports definite-length + * values, which DER-encoded signatures should be. + */ + if (hdr[1] == 0x80) + { + WARN("indefinite-length encoding not supported!\n"); + goto freestream; + } + else if (hdr[1] & 0x80) + { + DWORD temp; + LPBYTE ptr; + + lenBytes = hdr[1] & 0x7f; + if (lenBytes > sizeof(DWORD)) + { + WARN("asn.1 length too long (%d)\n", lenBytes); + goto freestream; + } + r = IStream_Read(stm, len, lenBytes, &count); + if (FAILED(r) || count != lenBytes) + goto freestream; + dataBytes = 0; + temp = lenBytes; + ptr = len; + while (temp--) + { + dataBytes <<= 8; + dataBytes |= *ptr++; + } + } + else + { + lenBytes = 0; + dataBytes = hdr[1]; + } + + if (!pbSignedDataMsg) + { + *pcbSignedDataMsg = 2 + lenBytes + dataBytes; + ret = TRUE; + } + else if (*pcbSignedDataMsg < 2 + lenBytes + dataBytes) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + *pcbSignedDataMsg = 2 + lenBytes + dataBytes; + } + else + { + LPBYTE ptr = pbSignedDataMsg; + + memcpy(ptr, hdr, sizeof(hdr)); + ptr += sizeof(hdr); + if (lenBytes) + { + memcpy(ptr, len, lenBytes); + ptr += lenBytes; + } + r = IStream_Read(stm, ptr, dataBytes, &count); + if (SUCCEEDED(r) && count == dataBytes) + { + *pdwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; + *pcbSignedDataMsg = 2 + lenBytes + dataBytes; + ret = TRUE; + } + } + +freestream: + IStream_Release(stm); +freestorage: + IStorage_Release(stg); +end: + + TRACE("returning %d\n", ret); + return ret; +} + +/*********************************************************************** + * MsiSIPIsMyTypeOfFile (MSISIP.@) + */ +BOOL WINAPI MsiSIPIsMyTypeOfFile(WCHAR *name, GUID *subject) +{ + static const WCHAR msi[] = { '.','m','s','i',0 }; + static const WCHAR msp[] = { '.','m','s','p',0 }; + BOOL ret = FALSE; + + TRACE("(%s, %p)\n", debugstr_w(name), subject); + + if (lstrlenW(name) < lstrlenW(msi)) + return FALSE; + else if (lstrcmpiW(name + lstrlenW(name) - lstrlenW(msi), msi) && + lstrcmpiW(name + lstrlenW(name) - lstrlenW(msp), msp)) + return FALSE; + else + { + IStorage *stg = NULL; + HRESULT r = StgOpenStorage(name, NULL, + STGM_DIRECT|STGM_READ|STGM_SHARE_DENY_WRITE, NULL, 0, &stg); + + if (SUCCEEDED(r)) + { + IStorage_Release(stg); + *subject = mySubject; + ret = TRUE; + } + } + return ret; +} diff --git a/dlls/msisip/msisip.spec b/dlls/msisip/msisip.spec new file mode 100644 index 00000000000..cfe829249cb --- /dev/null +++ b/dlls/msisip/msisip.spec @@ -0,0 +1,8 @@ +5 stdcall MsiSIPIsMyTypeOfFile(wstr ptr) +6 stdcall MsiSIPGetSignedDataMsg(ptr ptr long ptr ptr) +7 stub MsiSIPPutSignedDataMsg +8 stub MsiSIPRemoveSignedDataMsg +9 stub MsiSIPCreateIndirectData +10 stub MsiSIPVerifyIndirectData +11 stdcall DllRegisterServer() +12 stdcall DllUnregisterServer() diff --git a/dlls/mstask/Makefile.in b/dlls/mstask/Makefile.in index 2202e227561..ae6a99f750e 100644 --- a/dlls/mstask/Makefile.in +++ b/dlls/mstask/Makefile.in @@ -10,6 +10,8 @@ C_SRCS = \ mstask_main.c \ task_scheduler.c +RC_SRCS = rsrc.rc + IDL_I_SRCS = mstask_local.idl @MAKE_DLL_RULES@ diff --git a/dlls/mstask/mstask.inf b/dlls/mstask/mstask.inf new file mode 100644 index 00000000000..10560933fdf --- /dev/null +++ b/dlls/mstask/mstask.inf @@ -0,0 +1,16 @@ +[version] +Signature="$CHICAGO$" + +[RegisterDll] +AddReg=Classes.Reg + +[UnregisterDll] +DelReg=Classes.Reg + +[Classes.Reg] +HKCR,"CLSID\%CLSID_CTaskScheduler%",,,"CTaskScheduler" +HKCR,"CLSID\%CLSID_CTaskScheduler%\InProcServer32",,,"mstask.dll" +HKCR,"CLSID\%CLSID_CTaskScheduler%\InProcServer32","ThreadingModel",,"Both" +HKCR,"CLSID\%CLSID_CTask%",,,"CTask" +HKCR,"CLSID\%CLSID_CTask%\InProcServer32",,,"mstask.dll" +HKCR,"CLSID\%CLSID_CTask%\InProcServer32","ThreadingModel",,"Both" diff --git a/dlls/mstask/mstask.spec b/dlls/mstask/mstask.spec index 24d5af52ccb..0b6c23b79de 100644 --- a/dlls/mstask/mstask.spec +++ b/dlls/mstask/mstask.spec @@ -24,3 +24,5 @@ @ stub _SASetAccountInformation@20 @ stub _SASetNSAccountInformation@12 @ stub _SetNetScheduleAccountInformation@12 +@ stdcall -private DllRegisterServer() +@ stdcall -private DllUnregisterServer() diff --git a/dlls/mstask/mstask_main.c b/dlls/mstask/mstask_main.c index 61e0a99c813..c7b3dea5a1b 100644 --- a/dlls/mstask/mstask_main.c +++ b/dlls/mstask/mstask_main.c @@ -16,11 +16,18 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include + #include "mstask_private.h" +#include "winreg.h" +#include "advpub.h" + #include "wine/debug.h" + WINE_DEFAULT_DEBUG_CHANNEL(mstask); +static HINSTANCE hInst; LONG dll_ref = 0; BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) @@ -33,6 +40,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return FALSE; case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL); + hInst = hinstDLL; break; case DLL_PROCESS_DETACH: break; @@ -57,3 +65,98 @@ HRESULT WINAPI DllCanUnloadNow(void) { return dll_ref != 0 ? S_FALSE : S_OK; } + +static inline char *mstask_strdup(const char *s) +{ + size_t n = strlen(s) + 1; + char *d = HeapAlloc(GetProcessHeap(), 0, n); + return d ? memcpy(d, s, n) : NULL; +} + +static HRESULT init_register_strtable(STRTABLEA *strtable) +{ +#define CLSID_EXPANSION_ENTRY(id) { "CLSID_" #id, &CLSID_ ## id } + static const struct + { + const char *name; + const CLSID *clsid; + } + expns[] = + { + CLSID_EXPANSION_ENTRY(CTaskScheduler), + CLSID_EXPANSION_ENTRY(CTask) + }; +#undef CLSID_EXPANSION_ENTRY + static STRENTRYA pse[sizeof expns / sizeof expns[0]]; + int i; + + strtable->cEntries = sizeof pse / sizeof pse[0]; + strtable->pse = pse; + for (i = 0; i < strtable->cEntries; i++) + { + static const char dummy_sample[] = + "{12345678-1234-1234-1234-123456789012}"; + const CLSID *clsid = expns[i].clsid; + pse[i].pszName = mstask_strdup(expns[i].name); + pse[i].pszValue = HeapAlloc(GetProcessHeap(), 0, sizeof dummy_sample); + if (!pse[i].pszName || !pse[i].pszValue) + return E_OUTOFMEMORY; + sprintf(pse[i].pszValue, + "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + clsid->Data1, clsid->Data2, clsid->Data3, clsid->Data4[0], + clsid->Data4[1], clsid->Data4[2], clsid->Data4[3], + clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], + clsid->Data4[7]); + } + + return S_OK; +} + +static void cleanup_register_strtable(STRTABLEA *strtable) +{ + int i; + for (i = 0; i < strtable->cEntries; i++) + { + HeapFree(GetProcessHeap(), 0, strtable->pse[i].pszName); + HeapFree(GetProcessHeap(), 0, strtable->pse[i].pszValue); + if (!strtable->pse[i].pszName || !strtable->pse[i].pszValue) + return; + } +} + +static HRESULT register_mstask(BOOL do_register) +{ + HRESULT hr; + STRTABLEA strtable; + HMODULE hAdvpack; + HRESULT (WINAPI *pRegInstall)(HMODULE hm, + LPCSTR pszSection, const STRTABLEA* pstTable); + static const WCHAR wszAdvpack[] = + {'a','d','v','p','a','c','k','.','d','l','l',0}; + + TRACE("(%x)\n", do_register); + + hAdvpack = LoadLibraryW(wszAdvpack); + pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall"); + + hr = init_register_strtable(&strtable); + if (SUCCEEDED(hr)) + hr = pRegInstall(hInst, do_register ? "RegisterDll" : "UnregisterDll", + &strtable); + cleanup_register_strtable(&strtable); + + if (FAILED(hr)) + WINE_ERR("RegInstall failed: %08x\n", hr); + + return hr; +} + +HRESULT WINAPI DllRegisterServer(void) +{ + return register_mstask(TRUE); +} + +HRESULT WINAPI DllUnregisterServer(void) +{ + return register_mstask(FALSE); +} diff --git a/include/intshcut.h b/dlls/mstask/rsrc.rc similarity index 72% copy from include/intshcut.h copy to dlls/mstask/rsrc.rc index 54c2f2d1c19..9915e028c48 100644 --- a/include/intshcut.h +++ b/dlls/mstask/rsrc.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Francois Gouget + * Copyright 2008 Google (Roy Shea) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,21 +16,5 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_INTSHCUT_H -#define __WINE_INTSHCUT_H - -/* FIXME: #include */ - -#define INTSHCUTAPI - -#ifdef __cplusplus -extern "C" { -#endif - -BOOL WINAPI InetIsOffline(DWORD); - -#ifdef __cplusplus -} -#endif - -#endif /* __WINE_INTSHCUT_H */ +/* @makedep: mstask.inf */ +REGINST REGINST mstask.inf diff --git a/dlls/msxml3/Makefile.in b/dlls/msxml3/Makefile.in index ef82edceab8..b02253f931a 100644 --- a/dlls/msxml3/Makefile.in +++ b/dlls/msxml3/Makefile.in @@ -10,6 +10,7 @@ EXTRAINCL = @XML2INCL@ @XSLTINCL@ C_SRCS = \ attribute.c \ + bsc.c \ cdata.c \ comment.c \ docfrag.c \ diff --git a/dlls/msxml3/bsc.c b/dlls/msxml3/bsc.c new file mode 100644 index 00000000000..bd29c318f00 --- /dev/null +++ b/dlls/msxml3/bsc.c @@ -0,0 +1,310 @@ +/* + * Copyright 2008 Piotr Caban + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#define NONAMELESSUNION + +#include "config.h" + +#include +#include +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "ole2.h" +#include "msxml2.h" +#include "wininet.h" +#include "urlmon.h" +#include "winreg.h" +#include "shlwapi.h" + +#include "wine/debug.h" + +#include "msxml_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msxml); + +struct bsc_t { + const struct IBindStatusCallbackVtbl *lpVtbl; + + LONG ref; + + void *obj; + HRESULT (*onDataAvailable)(void*,char*,DWORD); + + IBinding *binding; + IStream *memstream; +}; + +static inline bsc_t *impl_from_IBindStatusCallback( IBindStatusCallback *iface ) +{ + return (bsc_t *)((char*)iface - FIELD_OFFSET(bsc_t, lpVtbl)); +} + +static HRESULT WINAPI bsc_QueryInterface( + IBindStatusCallback *iface, + REFIID riid, + LPVOID *ppobj ) +{ + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IBindStatusCallback)) + { + IBindStatusCallback_AddRef( iface ); + *ppobj = iface; + return S_OK; + } + + FIXME("interface %s not implemented\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI bsc_AddRef( + IBindStatusCallback *iface ) +{ + bsc_t *This = impl_from_IBindStatusCallback(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + return ref; +} + +static ULONG WINAPI bsc_Release( + IBindStatusCallback *iface ) +{ + bsc_t *This = impl_from_IBindStatusCallback(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%d\n", This, ref); + + if(!ref) { + if(This->binding) + IBinding_Release(This->binding); + if(This->memstream) + IStream_Release(This->memstream); + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} + +static HRESULT WINAPI bsc_OnStartBinding( + IBindStatusCallback* iface, + DWORD dwReserved, + IBinding* pib) +{ + bsc_t *This = impl_from_IBindStatusCallback(iface); + HRESULT hr; + + TRACE("(%p)->(%x %p)\n", This, dwReserved, pib); + + This->binding = pib; + IBindStatusCallback_AddRef(pib); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &This->memstream); + if(FAILED(hr)) + return hr; + + return S_OK; +} + +static HRESULT WINAPI bsc_GetPriority( + IBindStatusCallback* iface, + LONG* pnPriority) +{ + return S_OK; +} + +static HRESULT WINAPI bsc_OnLowResource( + IBindStatusCallback* iface, + DWORD reserved) +{ + return S_OK; +} + +static HRESULT WINAPI bsc_OnProgress( + IBindStatusCallback* iface, + ULONG ulProgress, + ULONG ulProgressMax, + ULONG ulStatusCode, + LPCWSTR szStatusText) +{ + return S_OK; +} + +static HRESULT WINAPI bsc_OnStopBinding( + IBindStatusCallback* iface, + HRESULT hresult, + LPCWSTR szError) +{ + bsc_t *This = impl_from_IBindStatusCallback(iface); + HRESULT hr = S_OK; + + TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError)); + + if(This->binding) { + IBinding_Release(This->binding); + This->binding = NULL; + } + + if(This->obj && SUCCEEDED(hresult)) { + HGLOBAL hglobal; + hr = GetHGlobalFromStream(This->memstream, &hglobal); + if(SUCCEEDED(hr)) + { + DWORD len = GlobalSize(hglobal); + char *ptr = GlobalLock(hglobal); + + hr = This->onDataAvailable(This->obj, ptr, len); + + GlobalUnlock(hglobal); + } + } + + return hr; +} + +static HRESULT WINAPI bsc_GetBindInfo( + IBindStatusCallback* iface, + DWORD* grfBINDF, + BINDINFO* pbindinfo) +{ + *grfBINDF = BINDF_GETNEWESTVERSION|BINDF_PULLDATA|BINDF_RESYNCHRONIZE|BINDF_PRAGMA_NO_CACHE; + + return S_OK; +} + +static HRESULT WINAPI bsc_OnDataAvailable( + IBindStatusCallback* iface, + DWORD grfBSCF, + DWORD dwSize, + FORMATETC* pformatetc, + STGMEDIUM* pstgmed) +{ + bsc_t *This = impl_from_IBindStatusCallback(iface); + BYTE buf[4096]; + DWORD read, written; + HRESULT hr; + + TRACE("(%p)->(%x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed); + + do + { + hr = IStream_Read(pstgmed->u.pstm, buf, sizeof(buf), &read); + if(FAILED(hr)) + break; + + hr = IStream_Write(This->memstream, buf, read, &written); + } while(SUCCEEDED(hr) && written != 0 && read != 0); + + return S_OK; +} + +static HRESULT WINAPI bsc_OnObjectAvailable( + IBindStatusCallback* iface, + REFIID riid, + IUnknown* punk) +{ + return S_OK; +} + +static const struct IBindStatusCallbackVtbl bsc_vtbl = +{ + bsc_QueryInterface, + bsc_AddRef, + bsc_Release, + bsc_OnStartBinding, + bsc_GetPriority, + bsc_OnLowResource, + bsc_OnProgress, + bsc_OnStopBinding, + bsc_GetBindInfo, + bsc_OnDataAvailable, + bsc_OnObjectAvailable +}; + +HRESULT bind_url(LPCWSTR url, HRESULT (*onDataAvailable)(void*,char*,DWORD), void *obj, bsc_t **ret) +{ + WCHAR fileUrl[INTERNET_MAX_URL_LENGTH]; + bsc_t *bsc; + IBindCtx *pbc; + HRESULT hr; + + TRACE("%s\n", debugstr_w(url)); + + if(!PathIsURLW(url)) + { + WCHAR fullpath[MAX_PATH]; + DWORD needed = sizeof(fileUrl)/sizeof(WCHAR); + + if(!PathSearchAndQualifyW(url, fullpath, sizeof(fullpath)/sizeof(WCHAR))) + { + WARN("can't find path\n"); + return E_FAIL; + } + + if(FAILED(UrlCreateFromPathW(url, fileUrl, &needed, 0))) + { + ERR("can't create url from path\n"); + return E_FAIL; + } + url = fileUrl; + } + + hr = CreateBindCtx(0, &pbc); + if(FAILED(hr)) + return hr; + + bsc = HeapAlloc(GetProcessHeap(), 0, sizeof(bsc_t)); + + bsc->lpVtbl = &bsc_vtbl; + bsc->ref = 1; + bsc->obj = obj; + bsc->onDataAvailable = onDataAvailable; + bsc->binding = NULL; + bsc->memstream = NULL; + + hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)&bsc->lpVtbl, NULL, 0); + if(SUCCEEDED(hr)) + { + IMoniker *moniker; + + hr = CreateURLMoniker(NULL, url, &moniker); + if(SUCCEEDED(hr)) + { + IStream *stream; + hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (LPVOID*)&stream); + IMoniker_Release(moniker); + if(stream) + IStream_Release(stream); + } + IBindCtx_Release(pbc); + } + + *ret = bsc; + return hr; +} + +void detach_bsc(bsc_t *bsc) +{ + if(bsc->binding) + IBinding_Abort(bsc->binding); + + bsc->obj = NULL; + IBindStatusCallback_Release((IBindStatusCallback*)&bsc->lpVtbl); +} diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c index 3952b5e9e7c..8e39391f950 100644 --- a/dlls/msxml3/domdoc.c +++ b/dlls/msxml3/domdoc.c @@ -32,7 +32,6 @@ #include "ole2.h" #include "msxml2.h" #include "wininet.h" -#include "urlmon.h" #include "winreg.h" #include "shlwapi.h" #include "ocidl.h" @@ -50,8 +49,6 @@ static const WCHAR SZ_PROPERTY_SELECTION_LANGUAGE[] = {'S','e','l','e','c','t',' static const WCHAR SZ_VALUE_XPATH[] = {'X','P','a','t','h',0}; static const WCHAR SZ_VALUE_XSLPATTERN[] = {'X','S','L','P','a','t','t','e','r','n',0}; -typedef struct bsc_t bsc_t; - typedef struct _domdoc { const struct IXMLDOMDocument2Vtbl *lpVtbl; @@ -80,21 +77,6 @@ typedef struct _domdoc DWORD safeopt; } domdoc; -struct bsc_t { - const struct IBindStatusCallbackVtbl *lpVtbl; - - LONG ref; - - domdoc *doc; - IBinding *binding; - IStream *memstream; -}; - -static inline bsc_t *impl_from_IBindStatusCallback( IBindStatusCallback *iface ) -{ - return (bsc_t *)((char*)iface - FIELD_OFFSET(bsc_t, lpVtbl)); -} - static xmlDocPtr doparse( char *ptr, int len ) { #ifdef HAVE_XMLREADMEMORY @@ -109,208 +91,6 @@ static xmlDocPtr doparse( char *ptr, int len ) #endif } -static HRESULT WINAPI bsc_QueryInterface( - IBindStatusCallback *iface, - REFIID riid, - LPVOID *ppobj ) -{ - if (IsEqualGUID(riid, &IID_IUnknown) || - IsEqualGUID(riid, &IID_IBindStatusCallback)) - { - IBindStatusCallback_AddRef( iface ); - *ppobj = iface; - return S_OK; - } - - FIXME("interface %s not implemented\n", debugstr_guid(riid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI bsc_AddRef( - IBindStatusCallback *iface ) -{ - bsc_t *This = impl_from_IBindStatusCallback(iface); - LONG ref = InterlockedIncrement(&This->ref); - - TRACE("(%p) ref=%d\n", This, ref); - - return ref; -} - -static ULONG WINAPI bsc_Release( - IBindStatusCallback *iface ) -{ - bsc_t *This = impl_from_IBindStatusCallback(iface); - LONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p) ref=%d\n", This, ref); - - if(!ref) { - if(This->binding) - IBinding_Release(This->binding); - if(This->doc && This->doc->bsc == This) - This->doc->bsc = NULL; - if(This->memstream) - IStream_Release(This->memstream); - HeapFree(GetProcessHeap(), 0, This); - } - - return ref; -} - -static HRESULT WINAPI bsc_OnStartBinding( - IBindStatusCallback* iface, - DWORD dwReserved, - IBinding* pib) -{ - bsc_t *This = impl_from_IBindStatusCallback(iface); - HRESULT hr; - - TRACE("(%p)->(%x %p)\n", This, dwReserved, pib); - - This->binding = pib; - IBindStatusCallback_AddRef(pib); - - hr = CreateStreamOnHGlobal(NULL, TRUE, &This->memstream); - if(FAILED(hr)) - return hr; - - return S_OK; -} - -static HRESULT WINAPI bsc_GetPriority( - IBindStatusCallback* iface, - LONG* pnPriority) -{ - return S_OK; -} - -static HRESULT WINAPI bsc_OnLowResource( - IBindStatusCallback* iface, - DWORD reserved) -{ - return S_OK; -} - -static HRESULT WINAPI bsc_OnProgress( - IBindStatusCallback* iface, - ULONG ulProgress, - ULONG ulProgressMax, - ULONG ulStatusCode, - LPCWSTR szStatusText) -{ - return S_OK; -} - -static HRESULT WINAPI bsc_OnStopBinding( - IBindStatusCallback* iface, - HRESULT hresult, - LPCWSTR szError) -{ - bsc_t *This = impl_from_IBindStatusCallback(iface); - HRESULT hr; - - TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError)); - - if(This->binding) { - IBinding_Release(This->binding); - This->binding = NULL; - } - - if(This->doc && SUCCEEDED(hresult)) { - HGLOBAL hglobal; - hr = GetHGlobalFromStream(This->memstream, &hglobal); - if(SUCCEEDED(hr)) - { - DWORD len = GlobalSize(hglobal); - char *ptr = GlobalLock(hglobal); - xmlDocPtr xmldoc; - if(len != 0) { - xmldoc = doparse( ptr, len ); - if(xmldoc) { - xmldoc->_private = 0; - attach_xmlnode(This->doc->node, (xmlNodePtr) xmldoc); - } - } - GlobalUnlock(hglobal); - } - } - - return S_OK; -} - -static HRESULT WINAPI bsc_GetBindInfo( - IBindStatusCallback* iface, - DWORD* grfBINDF, - BINDINFO* pbindinfo) -{ - *grfBINDF = BINDF_GETNEWESTVERSION|BINDF_PULLDATA|BINDF_RESYNCHRONIZE|BINDF_PRAGMA_NO_CACHE; - - return S_OK; -} - -static HRESULT WINAPI bsc_OnDataAvailable( - IBindStatusCallback* iface, - DWORD grfBSCF, - DWORD dwSize, - FORMATETC* pformatetc, - STGMEDIUM* pstgmed) -{ - bsc_t *This = impl_from_IBindStatusCallback(iface); - BYTE buf[4096]; - DWORD read, written; - HRESULT hr; - - TRACE("(%p)->(%x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed); - - do - { - hr = IStream_Read(pstgmed->u.pstm, buf, sizeof(buf), &read); - if(FAILED(hr)) - break; - - hr = IStream_Write(This->memstream, buf, read, &written); - } while(SUCCEEDED(hr) && written != 0 && read != 0); - - return S_OK; -} - -static HRESULT WINAPI bsc_OnObjectAvailable( - IBindStatusCallback* iface, - REFIID riid, - IUnknown* punk) -{ - return S_OK; -} - -static const struct IBindStatusCallbackVtbl bsc_vtbl = -{ - bsc_QueryInterface, - bsc_AddRef, - bsc_Release, - bsc_OnStartBinding, - bsc_GetPriority, - bsc_OnLowResource, - bsc_OnProgress, - bsc_OnStopBinding, - bsc_GetBindInfo, - bsc_OnDataAvailable, - bsc_OnObjectAvailable -}; - -static bsc_t *create_bsc(domdoc *doc) -{ - bsc_t *bsc = HeapAlloc(GetProcessHeap(), 0, sizeof(bsc_t)); - - bsc->lpVtbl = &bsc_vtbl; - bsc->ref = 1; - bsc->doc = doc; - bsc->binding = NULL; - bsc->memstream = NULL; - - return bsc; -} - LONG xmldoc_add_ref(xmlDocPtr doc) { LONG ref = InterlockedIncrement((LONG*)&doc->_private); @@ -547,12 +327,8 @@ static ULONG WINAPI domdoc_Release( ref = InterlockedDecrement( &This->ref ); if ( ref == 0 ) { - if(This->bsc) { - if(This->bsc->binding) - IBinding_Abort(This->bsc->binding); - This->bsc->doc = NULL; - IBindStatusCallback_Release((IBindStatusCallback*)&This->bsc->lpVtbl); - } + if(This->bsc) + detach_bsc(This->bsc); if (This->site) IUnknown_Release( This->site ); @@ -1395,63 +1171,34 @@ static HRESULT WINAPI domdoc_nodeFromID( return E_NOTIMPL; } -static HRESULT doread( domdoc *This, LPWSTR filename ) +static HRESULT domdoc_onDataAvailable(void *obj, char *ptr, DWORD len) { - HRESULT hr; - IBindCtx *pbc; - WCHAR url[INTERNET_MAX_URL_LENGTH]; - - TRACE("%s\n", debugstr_w( filename )); - - if(!PathIsURLW(filename)) - { - WCHAR fullpath[MAX_PATH]; - DWORD needed = sizeof(url)/sizeof(WCHAR); - - if(!PathSearchAndQualifyW(filename, fullpath, sizeof(fullpath)/sizeof(WCHAR))) - { - WARN("can't find path\n"); - return E_FAIL; - } + domdoc *This = obj; + xmlDocPtr xmldoc; - if(FAILED(UrlCreateFromPathW(fullpath, url, &needed, 0))) - { - ERR("can't create url from path\n"); - return E_FAIL; - } - filename = url; + xmldoc = doparse( ptr, len ); + if(xmldoc) { + xmldoc->_private = 0; + attach_xmlnode(This->node, (xmlNodePtr) xmldoc); } - hr = CreateBindCtx(0, &pbc); - if(SUCCEEDED(hr)) - { - if(This->bsc) { - if(This->bsc->binding) - IBinding_Abort(This->bsc->binding); - This->bsc->doc = NULL; - IBindStatusCallback_Release((IBindStatusCallback*)&This->bsc->lpVtbl); - } + return S_OK; +} - This->bsc = create_bsc(This); +static HRESULT doread( domdoc *This, LPWSTR filename ) +{ + bsc_t *bsc; + HRESULT hr; - hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)&This->bsc->lpVtbl, NULL, 0); - if(SUCCEEDED(hr)) - { - IMoniker *moniker; - hr = CreateURLMoniker(NULL, filename, &moniker); - if(SUCCEEDED(hr)) - { - IStream *stream; - hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (LPVOID*)&stream); - IMoniker_Release(moniker); - if(stream) - IStream_Release(stream); - } - } - IBindCtx_Release(pbc); - } + hr = bind_url(filename, domdoc_onDataAvailable, This, &bsc); + if(FAILED(hr)) + return hr; - return hr; + if(This->bsc) + detach_bsc(This->bsc); + + This->bsc = bsc; + return S_OK; } static HRESULT WINAPI domdoc_load( diff --git a/dlls/msxml3/main.c b/dlls/msxml3/main.c index 8c7d0d361cf..8a1496f5ea7 100644 --- a/dlls/msxml3/main.c +++ b/dlls/msxml3/main.c @@ -175,10 +175,18 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) case DLL_PROCESS_ATTACH: #ifdef HAVE_LIBXML2 xmlInitParser(); + + /* Set the default indent character to a single tab. */ + xmlThrDefTreeIndentString("\t"); #endif #ifdef HAVE_XSLTINIT xsltInit(); #endif + +#ifdef HAVE_LIBXML2 + /* Set the current ident to the default */ + xmlTreeIndentString = "\t"; +#endif hInstance = hInstDLL; DisableThreadLibraryCalls(hInstDLL); break; diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h index c365a11ab17..d065e3b553c 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -93,6 +93,11 @@ extern HRESULT SchemaCache_create( IUnknown *pUnkOuter, LPVOID *ppObj ); extern HRESULT XMLDocument_create( IUnknown *pUnkOuter, LPVOID *ppObj ); extern HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj ); +typedef struct bsc_t bsc_t; + +HRESULT bind_url(LPCWSTR, HRESULT (*onDataAvailable)(void*,char*,DWORD), void*, bsc_t**); +void detach_bsc(bsc_t*); + /* typelibs */ enum tid_t { IXMLDOMAttribute_tid, diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c index 583e0e1c0a4..68bf8818a45 100644 --- a/dlls/msxml3/node.c +++ b/dlls/msxml3/node.c @@ -1039,6 +1039,59 @@ static HRESULT WINAPI xmlnode_put_dataType( return hr; } +static BSTR EnsureCorrectEOL(BSTR sInput) +{ + static const WCHAR SZ_RETURN[] = {'\n',0}; + static const WCHAR SZ_LINEFEED[] = {'\r',0}; + int nNum = 0; + BSTR sNew; + int nLen; + int i; + + nLen = lstrlenW(sInput); + /* Count line endings */ + for(i=0; i < nLen; i++) + { + if(sInput[i] == SZ_RETURN[0]) + nNum++; + } + + TRACE("len=%d, num=%d\n", nLen, nNum); + + /* Add linefeed as needed */ + if(nNum > 0) + { + int nPlace = 0; + sNew = SysAllocStringLen(NULL, nLen + nNum+1); + for(i=0; i < nLen; i++) + { + if(sInput[i] == SZ_RETURN[0]) + { + sNew[i+nPlace] = SZ_LINEFEED[0]; + nPlace++; + } + sNew[i+nPlace] = sInput[i]; + } + + SysFreeString(sInput); + } + else + { + sNew = sInput; + } + + TRACE("len %d\n", lstrlenW(sNew)); + + return sNew; +} + +/* + * We are trying to replicate the same behaviour as msxml by converting + * line endings to \r\n and using idents as \t. The problem is that msxml + * only formats nodes that have a line ending. Using libxml we cannot + * reproduce behaviour exactly. + * + */ static HRESULT WINAPI xmlnode_get_xml( IXMLDOMNode *iface, BSTR* xmlString) @@ -1047,7 +1100,7 @@ static HRESULT WINAPI xmlnode_get_xml( xmlBufferPtr pXmlBuf; int nSize; - TRACE("iface %p\n", iface); + TRACE("iface %p %d\n", iface, This->node->type); if(!xmlString) return E_INVALIDARG; @@ -1057,21 +1110,23 @@ static HRESULT WINAPI xmlnode_get_xml( pXmlBuf = xmlBufferCreate(); if(pXmlBuf) { - nSize = xmlNodeDump(pXmlBuf, This->node->doc, This->node, 0, 0); + nSize = xmlNodeDump(pXmlBuf, This->node->doc, This->node, 0, 1); if(nSize > 0) { const xmlChar *pContent; + BSTR bstrContent; /* Attribute Nodes return a space in front of their name */ pContent = xmlBufferContent(pXmlBuf); if( ((char*)pContent)[0] == ' ') - *xmlString = bstr_from_xmlChar(pContent+1); + bstrContent = bstr_from_xmlChar(pContent+1); else - *xmlString = bstr_from_xmlChar(pContent); - + bstrContent = bstr_from_xmlChar(pContent); - xmlBufferFree(pXmlBuf); + *xmlString = This->node->type == XML_ELEMENT_NODE ? EnsureCorrectEOL(bstrContent) : bstrContent; } + + xmlBufferFree(pXmlBuf); } /* Always returns a string. */ diff --git a/dlls/msxml3/saxreader.c b/dlls/msxml3/saxreader.c index 3b67d019f86..0b44a6eb6d9 100644 --- a/dlls/msxml3/saxreader.c +++ b/dlls/msxml3/saxreader.c @@ -44,19 +44,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); #ifdef HAVE_LIBXML2 #include +#include typedef struct _saxreader { - const struct IVBSAXXMLReaderVtbl *lpVtbl; + const struct IVBSAXXMLReaderVtbl *lpVBSAXXMLReaderVtbl; const struct ISAXXMLReaderVtbl *lpSAXXMLReaderVtbl; LONG ref; struct ISAXContentHandler *contentHandler; + struct IVBSAXContentHandler *vbcontentHandler; struct ISAXErrorHandler *errorHandler; + struct IVBSAXErrorHandler *vberrorHandler; xmlSAXHandler sax; } saxreader; typedef struct _saxlocator { + const struct IVBSAXLocatorVtbl *lpVBSAXLocatorVtbl; const struct ISAXLocatorVtbl *lpSAXLocatorVtbl; LONG ref; saxreader *saxreader; @@ -67,11 +71,25 @@ typedef struct _saxlocator xmlChar *lastCur; int line; int column; + BOOL vbInterface; } saxlocator; +typedef struct _saxattributes +{ + const struct IVBSAXAttributesVtbl *lpVBSAXAttributesVtbl; + const struct ISAXAttributesVtbl *lpSAXAttributesVtbl; + LONG ref; + int nb_attributes; + BSTR *szLocalname; + BSTR *szPrefix; + BSTR *szURI; + BSTR *szValue; + BSTR *szQName; +} saxattributes; + static inline saxreader *impl_from_IVBSAXXMLReader( IVBSAXXMLReader *iface ) { - return (saxreader *)((char*)iface - FIELD_OFFSET(saxreader, lpVtbl)); + return (saxreader *)((char*)iface - FIELD_OFFSET(saxreader, lpVBSAXXMLReaderVtbl)); } static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface ) @@ -79,11 +97,48 @@ static inline saxreader *impl_from_ISAXXMLReader( ISAXXMLReader *iface ) return (saxreader *)((char*)iface - FIELD_OFFSET(saxreader, lpSAXXMLReaderVtbl)); } +static inline saxlocator *impl_from_IVBSAXLocator( IVBSAXLocator *iface ) +{ + return (saxlocator *)((char*)iface - FIELD_OFFSET(saxlocator, lpVBSAXLocatorVtbl)); +} + static inline saxlocator *impl_from_ISAXLocator( ISAXLocator *iface ) { return (saxlocator *)((char*)iface - FIELD_OFFSET(saxlocator, lpSAXLocatorVtbl)); } +static inline saxattributes *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface ) +{ + return (saxattributes *)((char*)iface - FIELD_OFFSET(saxattributes, lpVBSAXAttributesVtbl)); +} + +static inline saxattributes *impl_from_ISAXAttributes( ISAXAttributes *iface ) +{ + return (saxattributes *)((char*)iface - FIELD_OFFSET(saxattributes, lpSAXAttributesVtbl)); +} + + +BSTR bstr_from_xmlCharN(const xmlChar *buf, int len) +{ + DWORD dLen; + LPWSTR str; + BSTR bstr; + + if (!buf) + return NULL; + + dLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0); + if(len != -1) dLen++; + str = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dLen * sizeof (WCHAR)); + if (!str) + return NULL; + MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, dLen); + if(len != -1) str[dLen-1] = '\0'; + bstr = SysAllocString(str); + HeapFree(GetProcessHeap(), 0, str); + + return bstr; +} static void format_error_message_from_id(saxlocator *This, HRESULT hr) { @@ -100,8 +155,15 @@ static void format_error_message_from_id(saxlocator *This, HRESULT hr) msg[0] = '\0'; } - ISAXErrorHandler_fatalError(This->saxreader->errorHandler, - (ISAXLocator*)&This->lpSAXLocatorVtbl, msg, hr); + if(This->vbInterface) + { + BSTR bstrMsg = SysAllocString(msg); + IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler, + (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrMsg, hr); + } + else + ISAXErrorHandler_fatalError(This->saxreader->errorHandler, + (ISAXLocator*)&This->lpSAXLocatorVtbl, msg, hr); } } @@ -113,6 +175,12 @@ static void update_position(saxlocator *This, xmlChar *end) This->line = 1; This->column = 1; } + else if(This->lastCur < This->pParserCtxt->input->base) + { + This->lastCur = (xmlChar*)This->pParserCtxt->input->base; + This->line = 1; + This->column = 1; + } if(!end) end = (xmlChar*)This->pParserCtxt->input->cur; @@ -134,212 +202,897 @@ static void update_position(saxlocator *This, xmlChar *end) } } -/*** LibXML callbacks ***/ -static void libxmlStartDocument(void *ctx) +/*** IVBSAXAttributes interface ***/ +/*** IUnknown methods ***/ +static HRESULT WINAPI ivbsaxattributes_QueryInterface( + IVBSAXAttributes* iface, + REFIID riid, + void **ppvObject) { - saxlocator *This = ctx; - HRESULT hr; + saxattributes *This = impl_from_IVBSAXAttributes(iface); - if(This->saxreader->contentHandler) + TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); + + *ppvObject = NULL; + + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IDispatch) || + IsEqualGUID(riid, &IID_IVBSAXAttributes)) { - hr = ISAXContentHandler_startDocument(This->saxreader->contentHandler); - if(hr != S_OK) - format_error_message_from_id(This, hr); + *ppvObject = iface; + } + else + { + FIXME("interface %s not implemented\n", debugstr_guid(riid)); + return E_NOINTERFACE; } - update_position(This, NULL); + IVBSAXAttributes_AddRef(iface); + + return S_OK; } -static void libxmlEndDocument(void *ctx) +static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface) { - saxlocator *This = ctx; - HRESULT hr; + saxattributes *This = impl_from_IVBSAXAttributes(iface); + return ISAXAttributes_AddRef((ISAXAttributes*)&This->lpSAXAttributesVtbl); +} - This->column = 0; - This->line = 0; +static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface) +{ + saxattributes *This = impl_from_IVBSAXAttributes(iface); + return ISAXAttributes_Release((ISAXAttributes*)&This->lpSAXAttributesVtbl); +} - if(This->ret != S_OK) return; +/*** IDispatch methods ***/ +static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo ) +{ + saxattributes *This = impl_from_IVBSAXAttributes( iface ); - if(This->saxreader->contentHandler) - { - hr = ISAXContentHandler_endDocument(This->saxreader->contentHandler); - if(hr != S_OK) - format_error_message_from_id(This, hr); - } + TRACE("(%p)->(%p)\n", This, pctinfo); + + *pctinfo = 1; + + return S_OK; } -static void libxmlStartElementNS( - void *ctx, - const xmlChar *localname, - const xmlChar *prefix, - const xmlChar *URI, - int nb_namespaces, - const xmlChar **namespaces, - int nb_attributes, - int nb_defaulted, - const xmlChar **attributes) +static HRESULT WINAPI ivbsaxattributes_GetTypeInfo( + IVBSAXAttributes *iface, + UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo ) { - BSTR NamespaceUri, LocalName, QName; - saxlocator *This = ctx; + saxattributes *This = impl_from_IVBSAXAttributes( iface ); HRESULT hr; - FIXME("Arguments processing not yet implemented.\n"); + TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); - update_position(This, (xmlChar*)This->pParserCtxt->input->cur+1); + hr = get_typeinfo(IVBSAXAttributes_tid, ppTInfo); - if(This->saxreader->contentHandler) - { - NamespaceUri = bstr_from_xmlChar(URI); - LocalName = bstr_from_xmlChar(localname); - QName = bstr_from_xmlChar(localname); + return hr; +} - hr = ISAXContentHandler_startElement( - This->saxreader->contentHandler, - NamespaceUri, SysStringLen(NamespaceUri), - LocalName, SysStringLen(LocalName), - QName, SysStringLen(QName), - NULL); +static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames( + IVBSAXAttributes *iface, + REFIID riid, + LPOLESTR* rgszNames, + UINT cNames, + LCID lcid, + DISPID* rgDispId) +{ + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + ITypeInfo *typeinfo; + HRESULT hr; - SysFreeString(NamespaceUri); - SysFreeString(LocalName); - SysFreeString(QName); + TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, + lcid, rgDispId); - if(hr != S_OK) - format_error_message_from_id(This, hr); + if(!rgszNames || cNames == 0 || !rgDispId) + return E_INVALIDARG; + + hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo); + if(SUCCEEDED(hr)) + { + hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); + ITypeInfo_Release(typeinfo); } + + return hr; } -static void libxmlEndElementNS( - void *ctx, - const xmlChar *localname, - const xmlChar *prefix, - const xmlChar *URI) +static HRESULT WINAPI ivbsaxattributes_Invoke( + IVBSAXAttributes *iface, + DISPID dispIdMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) { - BSTR NamespaceUri, LocalName, QName; - saxlocator *This = ctx; + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + ITypeInfo *typeinfo; HRESULT hr; - xmlChar *end; - end = This->lastCur; - while(*end != '<' && *(end+1) != '/') end++; - update_position(This, end+2); + TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), + lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); - if(This->saxreader->contentHandler) + hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo); + if(SUCCEEDED(hr)) { - NamespaceUri = bstr_from_xmlChar(URI); - LocalName = bstr_from_xmlChar(localname); - QName = bstr_from_xmlChar(localname); + hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXAttributesVtbl), dispIdMember, wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); + ITypeInfo_Release(typeinfo); + } - hr = ISAXContentHandler_endElement( - This->saxreader->contentHandler, - NamespaceUri, SysStringLen(NamespaceUri), - LocalName, SysStringLen(LocalName), - QName, SysStringLen(QName)); + return hr; +} - SysFreeString(NamespaceUri); - SysFreeString(LocalName); - SysFreeString(QName); +/*** IVBSAXAttributes methods ***/ +static HRESULT WINAPI ivbsaxattributes_get_length( + IVBSAXAttributes* iface, + int *nLength) +{ + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getLength( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + nLength); +} - if(hr != S_OK) - format_error_message_from_id(This, hr); - } +static HRESULT WINAPI ivbsaxattributes_getURI( + IVBSAXAttributes* iface, + int nIndex, + BSTR *uri) +{ + int len; + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getURI( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + nIndex, (const WCHAR**)uri, &len); } -static void libxmlCharacters( - void *ctx, - const xmlChar *ch, - int len) +static HRESULT WINAPI ivbsaxattributes_getLocalName( + IVBSAXAttributes* iface, + int nIndex, + BSTR *localName) { - BSTR Chars; - saxlocator *This = ctx; - HRESULT hr; - xmlChar *end; - xmlChar *lastCurCopy; - xmlChar *chEnd; - int columnCopy; - int lineCopy; + int len; + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getLocalName( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + nIndex, (const WCHAR**)localName, &len); +} + +static HRESULT WINAPI ivbsaxattributes_getQName( + IVBSAXAttributes* iface, + int nIndex, + BSTR *QName) +{ + int len; + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getQName( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + nIndex, (const WCHAR**)QName, &len); +} + +static HRESULT WINAPI ivbsaxattributes_getIndexFromName( + IVBSAXAttributes* iface, + BSTR uri, + BSTR localName, + int *index) +{ + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getIndexFromName( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + (const WCHAR*)uri, SysStringLen(uri), + (const WCHAR*)localName, SysStringLen(localName), index); +} + +static HRESULT WINAPI ivbsaxattributes_getIndexFromQName( + IVBSAXAttributes* iface, + BSTR QName, + int *index) +{ + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getIndexFromQName( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + (const WCHAR*)QName, SysStringLen(QName), index); +} + +static HRESULT WINAPI ivbsaxattributes_getType( + IVBSAXAttributes* iface, + int nIndex, + BSTR *type) +{ + int len; + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getType( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + nIndex, (const WCHAR**)type, &len); +} + +static HRESULT WINAPI ivbsaxattributes_getTypeFromName( + IVBSAXAttributes* iface, + BSTR uri, + BSTR localName, + BSTR *type) +{ + int len; + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getTypeFromName( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + (const WCHAR*)uri, SysStringLen(uri), + (const WCHAR*)localName, SysStringLen(localName), + (const WCHAR**)type, &len); +} + +static HRESULT WINAPI ivbsaxattributes_getTypeFromQName( + IVBSAXAttributes* iface, + BSTR QName, + BSTR *type) +{ + int len; + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getTypeFromQName( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + (const WCHAR*)QName, SysStringLen(QName), + (const WCHAR**)type, &len); +} + +static HRESULT WINAPI ivbsaxattributes_getValue( + IVBSAXAttributes* iface, + int nIndex, + BSTR *value) +{ + int len; + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getValue( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + nIndex, (const WCHAR**)value, &len); +} + +static HRESULT WINAPI ivbsaxattributes_getValueFromName( + IVBSAXAttributes* iface, + BSTR uri, + BSTR localName, + BSTR *value) +{ + int len; + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getValueFromName( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + (const WCHAR*)uri, SysStringLen(uri), + (const WCHAR*)localName, SysStringLen(localName), + (const WCHAR**)value, &len); +} + +static HRESULT WINAPI ivbsaxattributes_getValueFromQName( + IVBSAXAttributes* iface, + BSTR QName, + BSTR *value) +{ + int len; + saxattributes *This = impl_from_IVBSAXAttributes( iface ); + return ISAXAttributes_getValueFromQName( + (ISAXAttributes*)&This->lpSAXAttributesVtbl, + (const WCHAR*)QName, SysStringLen(QName), + (const WCHAR**)value, &len); +} + +static const struct IVBSAXAttributesVtbl ivbsaxattributes_vtbl = +{ + ivbsaxattributes_QueryInterface, + ivbsaxattributes_AddRef, + ivbsaxattributes_Release, + ivbsaxattributes_GetTypeInfoCount, + ivbsaxattributes_GetTypeInfo, + ivbsaxattributes_GetIDsOfNames, + ivbsaxattributes_Invoke, + ivbsaxattributes_get_length, + ivbsaxattributes_getURI, + ivbsaxattributes_getLocalName, + ivbsaxattributes_getQName, + ivbsaxattributes_getIndexFromName, + ivbsaxattributes_getIndexFromQName, + ivbsaxattributes_getType, + ivbsaxattributes_getTypeFromName, + ivbsaxattributes_getTypeFromQName, + ivbsaxattributes_getValue, + ivbsaxattributes_getValueFromName, + ivbsaxattributes_getValueFromQName +}; - if(*(This->lastCur-1) != '>' && *(This->lastCur-1) != '/') return; +/*** ISAXAttributes interface ***/ +/*** IUnknown methods ***/ +static HRESULT WINAPI isaxattributes_QueryInterface( + ISAXAttributes* iface, + REFIID riid, + void **ppvObject) +{ + saxattributes *This = impl_from_ISAXAttributes(iface); - if(*(This->lastCur-1) != '>') + TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); + + *ppvObject = NULL; + + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_ISAXAttributes)) { - end = (xmlChar*)This->pParserCtxt->input->cur-len; - while(*(end-1) != '>') end--; - update_position(This, end); + *ppvObject = iface; + } + else + { + FIXME("interface %s not implemented\n", debugstr_guid(riid)); + return E_NOINTERFACE; } - chEnd = This->lastCur+len; - while(*chEnd != '<') chEnd++; + ISAXAttributes_AddRef(iface); - Chars = bstr_from_xmlChar(ch); + return S_OK; +} - lastCurCopy = This->lastCur; - columnCopy = This->column; - lineCopy = This->line; - end = This->lastCur; +static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface) +{ + saxattributes *This = impl_from_ISAXAttributes(iface); + TRACE("%p\n", This); + return InterlockedIncrement(&This->ref); +} - if(This->saxreader->contentHandler) +static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface) +{ + saxattributes *This = impl_from_ISAXAttributes(iface); + LONG ref; + + TRACE("%p\n", This); + + ref = InterlockedDecrement(&This->ref); + if (ref==0) { - while(This->lastCur < chEnd) + int index; + for(index=0; indexnb_attributes; index++) { - end = This->lastCur; - while(end < chEnd-1) - { - if(*end == '\r') break; - end++; - } + SysFreeString(This->szLocalname[index]); + SysFreeString(This->szPrefix[index]); + SysFreeString(This->szURI[index]); + SysFreeString(This->szValue[index]); + } - Chars = bstr_from_xmlChar(This->lastCur); + HeapFree(GetProcessHeap(), 0, This->szLocalname); + HeapFree(GetProcessHeap(), 0, This->szPrefix); + HeapFree(GetProcessHeap(), 0, This->szURI); + HeapFree(GetProcessHeap(), 0, This->szValue); - if(*end == '\r' && *(end+1) == '\n') - { - memmove((WCHAR*)Chars+(end-This->lastCur), - (WCHAR*)Chars+(end-This->lastCur)+1, - (SysStringLen(Chars)-(end-This->lastCur))*sizeof(WCHAR)); - SysReAllocStringLen(&Chars, Chars, SysStringLen(Chars)-1); - } - else if(*end == '\r') Chars[end-This->lastCur] = '\n'; + HeapFree(GetProcessHeap(), 0, This); + } - hr = ISAXContentHandler_characters(This->saxreader->contentHandler, Chars, end-This->lastCur+1); - SysFreeString(Chars); - if(hr != S_OK) - { - format_error_message_from_id(This, hr); - return; - } + return ref; +} - if(*(end+1) == '\n') end++; - if(end < chEnd) end++; +/*** ISAXAttributes methods ***/ +static HRESULT WINAPI isaxattributes_getLength( + ISAXAttributes* iface, + int *length) +{ + saxattributes *This = impl_from_ISAXAttributes( iface ); - This->column += end-This->lastCur; - This->lastCur = end; - } + *length = This->nb_attributes; + TRACE("Length set to %d\n", *length); + return S_OK; +} - This->lastCur = lastCurCopy; - This->column = columnCopy; - This->line = lineCopy; - update_position(This, chEnd); - } +static HRESULT WINAPI isaxattributes_getURI( + ISAXAttributes* iface, + int nIndex, + const WCHAR **pUrl, + int *pUriSize) +{ + saxattributes *This = impl_from_ISAXAttributes( iface ); + + FIXME("(%p)->(%d) stub\n", This, nIndex); + return E_NOTIMPL; } -static void libxmlSetDocumentLocator( - void *ctx, - xmlSAXLocatorPtr loc) +static HRESULT WINAPI isaxattributes_getLocalName( + ISAXAttributes* iface, + int nIndex, + const WCHAR **pLocalName, + int *pLocalNameLength) { - saxlocator *This = ctx; - HRESULT hr; + saxattributes *This = impl_from_ISAXAttributes( iface ); + TRACE("(%p)->(%d)\n", This, nIndex); - hr = ISAXContentHandler_putDocumentLocator(This->saxreader->contentHandler, - (ISAXLocator*)&This->lpSAXLocatorVtbl); + if(nIndex >= This->nb_attributes) return E_INVALIDARG; - if(FAILED(hr)) - format_error_message_from_id(This, hr); + *pLocalNameLength = SysStringLen(This->szLocalname[nIndex]); + *pLocalName = This->szLocalname[nIndex]; + + return S_OK; } -void libxmlFatalError(void *ctx, const char *msg, ...) +static HRESULT WINAPI isaxattributes_getQName( + ISAXAttributes* iface, + int nIndex, + const WCHAR **pQName, + int *pQNameLength) { - saxlocator *This = ctx; - char message[1024]; + saxattributes *This = impl_from_ISAXAttributes( iface ); + TRACE("(%p)->(%d)\n", This, nIndex); + + if(nIndex >= This->nb_attributes) return E_INVALIDARG; + + *pQNameLength = SysStringLen(This->szQName[nIndex]); + *pQName = This->szQName[nIndex]; + + return S_OK; +} + +static HRESULT WINAPI isaxattributes_getName( + ISAXAttributes* iface, + int nIndex, + const WCHAR **pUri, + int *pUriLength, + const WCHAR **pLocalName, + int *pLocalNameSize, + const WCHAR **pQName, + int *pQNameLength) +{ + saxattributes *This = impl_from_ISAXAttributes( iface ); + + FIXME("(%p)->(%d) stub\n", This, nIndex); + return E_NOTIMPL; +} + +static HRESULT WINAPI isaxattributes_getIndexFromName( + ISAXAttributes* iface, + const WCHAR *pUri, + int cUriLength, + const WCHAR *pLocalName, + int cocalNameLength, + int *index) +{ + saxattributes *This = impl_from_ISAXAttributes( iface ); + + FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), cUriLength, + debugstr_w(pLocalName), cocalNameLength); + return E_NOTIMPL; +} + +static HRESULT WINAPI isaxattributes_getIndexFromQName( + ISAXAttributes* iface, + const WCHAR *pQName, + int nQNameLength, + int *index) +{ + saxattributes *This = impl_from_ISAXAttributes( iface ); + + FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQNameLength); + return E_NOTIMPL; +} + +static HRESULT WINAPI isaxattributes_getType( + ISAXAttributes* iface, + int nIndex, + const WCHAR **pType, + int *pTypeLength) +{ + saxattributes *This = impl_from_ISAXAttributes( iface ); + + FIXME("(%p)->(%d) stub\n", This, nIndex); + return E_NOTIMPL; +} + +static HRESULT WINAPI isaxattributes_getTypeFromName( + ISAXAttributes* iface, + const WCHAR *pUri, + int nUri, + const WCHAR *pLocalName, + int nLocalName, + const WCHAR **pType, + int *nType) +{ + saxattributes *This = impl_from_ISAXAttributes( iface ); + + FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri, + debugstr_w(pLocalName), nLocalName); + return E_NOTIMPL; +} + +static HRESULT WINAPI isaxattributes_getTypeFromQName( + ISAXAttributes* iface, + const WCHAR *pQName, + int nQName, + const WCHAR **pType, + int *nType) +{ + saxattributes *This = impl_from_ISAXAttributes( iface ); + + FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName); + return E_NOTIMPL; +} + +static HRESULT WINAPI isaxattributes_getValue( + ISAXAttributes* iface, + int nIndex, + const WCHAR **pValue, + int *nValue) +{ + saxattributes *This = impl_from_ISAXAttributes( iface ); + TRACE("(%p)->(%d)\n", This, nIndex); + + if(nIndex >= This->nb_attributes) return E_INVALIDARG; + + *nValue = SysStringLen(This->szValue[nIndex]); + *pValue = This->szValue[nIndex]; + + return S_OK; +} + +static HRESULT WINAPI isaxattributes_getValueFromName( + ISAXAttributes* iface, + const WCHAR *pUri, + int nUri, + const WCHAR *pLocalName, + int nLocalName, + const WCHAR **pValue, + int *nValue) +{ + saxattributes *This = impl_from_ISAXAttributes( iface ); + + FIXME("(%p)->(%s, %d, %s, %d) stub\n", This, debugstr_w(pUri), nUri, + debugstr_w(pLocalName), nLocalName); + return E_NOTIMPL; +} + +static HRESULT WINAPI isaxattributes_getValueFromQName( + ISAXAttributes* iface, + const WCHAR *pQName, + int nQName, + const WCHAR **pValue, + int *nValue) +{ + saxattributes *This = impl_from_ISAXAttributes( iface ); + + FIXME("(%p)->(%s, %d) stub\n", This, debugstr_w(pQName), nQName); + return E_NOTIMPL; +} + +static const struct ISAXAttributesVtbl isaxattributes_vtbl = +{ + isaxattributes_QueryInterface, + isaxattributes_AddRef, + isaxattributes_Release, + isaxattributes_getLength, + isaxattributes_getURI, + isaxattributes_getLocalName, + isaxattributes_getQName, + isaxattributes_getName, + isaxattributes_getIndexFromName, + isaxattributes_getIndexFromQName, + isaxattributes_getType, + isaxattributes_getTypeFromName, + isaxattributes_getTypeFromQName, + isaxattributes_getValue, + isaxattributes_getValueFromName, + isaxattributes_getValueFromQName +}; + +static HRESULT SAXAttributes_create(saxattributes **attr, + int nb_attributes, const xmlChar **xmlAttributes) +{ + saxattributes *attributes; + int index; + + attributes = HeapAlloc(GetProcessHeap(), 0, sizeof(*attributes)); + if(!attributes) + return E_OUTOFMEMORY; + + attributes->lpVBSAXAttributesVtbl = &ivbsaxattributes_vtbl; + attributes->lpSAXAttributesVtbl = &isaxattributes_vtbl; + attributes->ref = 1; + + attributes->nb_attributes = nb_attributes; + + attributes->szLocalname = + HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*nb_attributes); + attributes->szPrefix = + HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*nb_attributes); + attributes->szURI = + HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*nb_attributes); + attributes->szValue = + HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*nb_attributes); + attributes->szQName = + HeapAlloc(GetProcessHeap(), 0, sizeof(BSTR)*nb_attributes); + + if(!attributes->szLocalname || !attributes->szPrefix + || !attributes->szURI || !attributes->szValue + || !attributes->szQName) + { + if(attributes->szLocalname) + HeapFree(GetProcessHeap(), 0, attributes->szLocalname); + if(attributes->szPrefix) + HeapFree(GetProcessHeap(), 0, attributes->szPrefix); + if(attributes->szURI) + HeapFree(GetProcessHeap(), 0, attributes->szURI); + if(attributes->szValue) + HeapFree(GetProcessHeap(), 0, attributes->szValue); + if(attributes->szQName) + HeapFree(GetProcessHeap(), 0, attributes->szQName); + return E_FAIL; + } + + for(index=0; indexszLocalname[index] = + bstr_from_xmlChar(xmlAttributes[index*5]); + attributes->szPrefix[index] = + bstr_from_xmlChar(xmlAttributes[index*5+1]); + attributes->szURI[index] = + bstr_from_xmlChar(xmlAttributes[index*5+2]); + attributes->szValue[index] = + bstr_from_xmlCharN(xmlAttributes[index*5+3], + xmlAttributes[index*5+4]-xmlAttributes[index*5+3]); + + len1 = SysStringLen(attributes->szPrefix[index]); + len2 = SysStringLen(attributes->szLocalname[index]); + attributes->szQName[index] = SysAllocStringLen(NULL, len1+len2); + memcpy(attributes->szQName[index], attributes->szPrefix[index], + len1*sizeof(WCHAR)); + memcpy(attributes->szQName[index]+len1, + attributes->szLocalname[index], len2*sizeof(WCHAR)); + attributes->szQName[index][len1+len2] = '\0'; + } + + *attr = attributes; + + TRACE("returning %p\n", *attr); + + return S_OK; +} + +/*** LibXML callbacks ***/ +static void libxmlStartDocument(void *ctx) +{ + saxlocator *This = ctx; + HRESULT hr; + + if(This->saxreader->contentHandler) + { + if(This->vbInterface) + hr = IVBSAXContentHandler_startDocument(This->saxreader->vbcontentHandler); + else + hr = ISAXContentHandler_startDocument(This->saxreader->contentHandler); + + if(hr != S_OK) + format_error_message_from_id(This, hr); + } + + update_position(This, NULL); +} + +static void libxmlEndDocument(void *ctx) +{ + saxlocator *This = ctx; + HRESULT hr; + + This->column = 0; + This->line = 0; + + if(This->ret != S_OK) return; + + if(This->saxreader->contentHandler) + { + if(This->vbInterface) + hr = IVBSAXContentHandler_endDocument(This->saxreader->vbcontentHandler); + else + hr = ISAXContentHandler_endDocument(This->saxreader->contentHandler); + + if(hr != S_OK) + format_error_message_from_id(This, hr); + } +} + +static void libxmlStartElementNS( + void *ctx, + const xmlChar *localname, + const xmlChar *prefix, + const xmlChar *URI, + int nb_namespaces, + const xmlChar **namespaces, + int nb_attributes, + int nb_defaulted, + const xmlChar **attributes) +{ + BSTR NamespaceUri, LocalName, QName; + saxlocator *This = ctx; + HRESULT hr; + saxattributes *attr; + + update_position(This, (xmlChar*)This->pParserCtxt->input->cur+1); + + if(This->saxreader->contentHandler) + { + NamespaceUri = bstr_from_xmlChar(URI); + LocalName = bstr_from_xmlChar(localname); + QName = bstr_from_xmlChar(localname); + + hr = SAXAttributes_create(&attr, nb_attributes, attributes); + if(hr == S_OK) + { + if(This->vbInterface) + hr = IVBSAXContentHandler_startElement( + This->saxreader->vbcontentHandler, + &NamespaceUri, &LocalName, &QName, + (IVBSAXAttributes*)&attr->lpVBSAXAttributesVtbl); + else + hr = ISAXContentHandler_startElement( + This->saxreader->contentHandler, + NamespaceUri, SysStringLen(NamespaceUri), + LocalName, SysStringLen(LocalName), + QName, SysStringLen(QName), + (ISAXAttributes*)&attr->lpSAXAttributesVtbl); + + ISAXAttributes_Release((ISAXAttributes*)&attr->lpSAXAttributesVtbl); + } + + SysFreeString(NamespaceUri); + SysFreeString(LocalName); + SysFreeString(QName); + + if(hr != S_OK) + format_error_message_from_id(This, hr); + } +} + +static void libxmlEndElementNS( + void *ctx, + const xmlChar *localname, + const xmlChar *prefix, + const xmlChar *URI) +{ + BSTR NamespaceUri, LocalName, QName; + saxlocator *This = ctx; + HRESULT hr; + xmlChar *end; + + end = This->lastCur; + while(*end != '<' && *(end+1) != '/') end++; + update_position(This, end+2); + + if(This->saxreader->contentHandler) + { + NamespaceUri = bstr_from_xmlChar(URI); + LocalName = bstr_from_xmlChar(localname); + QName = bstr_from_xmlChar(localname); + + if(This->vbInterface) + hr = IVBSAXContentHandler_endElement( + This->saxreader->vbcontentHandler, + &NamespaceUri, &LocalName, &QName); + else + hr = ISAXContentHandler_endElement( + This->saxreader->contentHandler, + NamespaceUri, SysStringLen(NamespaceUri), + LocalName, SysStringLen(LocalName), + QName, SysStringLen(QName)); + + SysFreeString(NamespaceUri); + SysFreeString(LocalName); + SysFreeString(QName); + + if(hr != S_OK) + format_error_message_from_id(This, hr); + } +} + +static void libxmlCharacters( + void *ctx, + const xmlChar *ch, + int len) +{ + BSTR Chars; + saxlocator *This = ctx; + HRESULT hr; + xmlChar *end; + xmlChar *lastCurCopy; + xmlChar *chEnd; + int columnCopy; + int lineCopy; + + if(*(This->lastCur-1) != '>' && *(This->lastCur-1) != '/') return; + + if(*(This->lastCur-1) != '>') + { + end = (xmlChar*)This->pParserCtxt->input->cur-len; + while(*(end-1) != '>') end--; + update_position(This, end); + } + + chEnd = This->lastCur+len; + while(*chEnd != '<') chEnd++; + + Chars = bstr_from_xmlChar(ch); + + lastCurCopy = This->lastCur; + columnCopy = This->column; + lineCopy = This->line; + end = This->lastCur; + + if(This->saxreader->contentHandler) + { + while(This->lastCur < chEnd) + { + end = This->lastCur; + while(end < chEnd-1) + { + if(*end == '\r') break; + end++; + } + + Chars = bstr_from_xmlChar(This->lastCur); + + if(*end == '\r' && *(end+1) == '\n') + { + memmove((WCHAR*)Chars+(end-This->lastCur), + (WCHAR*)Chars+(end-This->lastCur)+1, + (SysStringLen(Chars)-(end-This->lastCur))*sizeof(WCHAR)); + SysReAllocStringLen(&Chars, Chars, SysStringLen(Chars)-1); + } + else if(*end == '\r') Chars[end-This->lastCur] = '\n'; + + if(This->vbInterface) + hr = IVBSAXContentHandler_characters( + This->saxreader->vbcontentHandler, &Chars); + else + hr = ISAXContentHandler_characters( + This->saxreader->contentHandler, + Chars, end-This->lastCur+1); + + SysFreeString(Chars); + if(hr != S_OK) + { + format_error_message_from_id(This, hr); + return; + } + + if(*(end+1) == '\n') end++; + if(end < chEnd) end++; + + This->column += end-This->lastCur; + This->lastCur = end; + } + + This->lastCur = lastCurCopy; + This->column = columnCopy; + This->line = lineCopy; + update_position(This, chEnd); + } +} + +static void libxmlSetDocumentLocator( + void *ctx, + xmlSAXLocatorPtr loc) +{ + saxlocator *This = ctx; + HRESULT hr; + + if(This->vbInterface) + hr = IVBSAXContentHandler_putref_documentLocator( + This->saxreader->vbcontentHandler, + (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl); + else + hr = ISAXContentHandler_putDocumentLocator( + This->saxreader->contentHandler, + (ISAXLocator*)&This->lpSAXLocatorVtbl); + + if(FAILED(hr)) + format_error_message_from_id(This, hr); +} + +void libxmlFatalError(void *ctx, const char *msg, ...) +{ + saxlocator *This = ctx; + char message[1024]; WCHAR *wszError; DWORD len; va_list args; @@ -361,15 +1114,202 @@ void libxmlFatalError(void *ctx, const char *msg, ...) wszError = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len); MultiByteToWideChar(CP_ACP, 0, message, -1, (LPWSTR)wszError, len); - ISAXErrorHandler_fatalError(This->saxreader->errorHandler, - (ISAXLocator*)&This->lpSAXLocatorVtbl, wszError, E_FAIL); + if(This->vbInterface) + { + BSTR bstrError = SysAllocString(wszError); + IVBSAXErrorHandler_fatalError(This->saxreader->vberrorHandler, + (IVBSAXLocator*)&This->lpVBSAXLocatorVtbl, &bstrError, E_FAIL); + } + else + ISAXErrorHandler_fatalError(This->saxreader->errorHandler, + (ISAXLocator*)&This->lpSAXLocatorVtbl, wszError, E_FAIL); + + HeapFree(GetProcessHeap(), 0, wszError); + + xmlStopParser(This->pParserCtxt); + This->ret = E_FAIL; +} + +/*** IVBSAXLocator interface ***/ +/*** IUnknown methods ***/ +static HRESULT WINAPI ivbsaxlocator_QueryInterface(IVBSAXLocator* iface, REFIID riid, void **ppvObject) +{ + saxlocator *This = impl_from_IVBSAXLocator( iface ); + + TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject); + + *ppvObject = NULL; + + if ( IsEqualGUID( riid, &IID_IUnknown ) || + IsEqualGUID( riid, &IID_IDispatch) || + IsEqualGUID( riid, &IID_IVBSAXLocator )) + { + *ppvObject = iface; + } + else + { + FIXME("interface %s not implemented\n", debugstr_guid(riid)); + return E_NOINTERFACE; + } + + IVBSAXLocator_AddRef( iface ); + + return S_OK; +} + +static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface) +{ + saxlocator *This = impl_from_IVBSAXLocator( iface ); + TRACE("%p\n", This ); + return InterlockedIncrement( &This->ref ); +} + +static ULONG WINAPI ivbsaxlocator_Release( + IVBSAXLocator* iface) +{ + saxlocator *This = impl_from_IVBSAXLocator( iface ); + return ISAXLocator_Release((ISAXLocator*)&This->lpVBSAXLocatorVtbl); +} + +/*** IDispatch methods ***/ +static HRESULT WINAPI ivbsaxlocator_GetTypeInfoCount( IVBSAXLocator *iface, UINT* pctinfo ) +{ + saxlocator *This = impl_from_IVBSAXLocator( iface ); + + TRACE("(%p)->(%p)\n", This, pctinfo); + + *pctinfo = 1; + + return S_OK; +} + +static HRESULT WINAPI ivbsaxlocator_GetTypeInfo( + IVBSAXLocator *iface, + UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo ) +{ + saxlocator *This = impl_from_IVBSAXLocator( iface ); + HRESULT hr; + + TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); + + hr = get_typeinfo(IVBSAXLocator_tid, ppTInfo); + + return hr; +} + +static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames( + IVBSAXLocator *iface, + REFIID riid, + LPOLESTR* rgszNames, + UINT cNames, + LCID lcid, + DISPID* rgDispId) +{ + saxlocator *This = impl_from_IVBSAXLocator( iface ); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, + lcid, rgDispId); + + if(!rgszNames || cNames == 0 || !rgDispId) + return E_INVALIDARG; + + hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo); + if(SUCCEEDED(hr)) + { + hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI ivbsaxlocator_Invoke( + IVBSAXLocator *iface, + DISPID dispIdMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + saxlocator *This = impl_from_IVBSAXLocator( iface ); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), + lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + + hr = get_typeinfo(IVBSAXLocator_tid, &typeinfo); + if(SUCCEEDED(hr)) + { + hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXLocatorVtbl), dispIdMember, wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +/*** IVBSAXLocator methods ***/ +static HRESULT WINAPI ivbsaxlocator_get_columnNumber( + IVBSAXLocator* iface, + int *pnColumn) +{ + saxlocator *This = impl_from_IVBSAXLocator( iface ); + return ISAXLocator_getColumnNumber( + (ISAXLocator*)&This->lpVBSAXLocatorVtbl, + pnColumn); +} + +static HRESULT WINAPI ivbsaxlocator_get_lineNumber( + IVBSAXLocator* iface, + int *pnLine) +{ + saxlocator *This = impl_from_IVBSAXLocator( iface ); + return ISAXLocator_getLineNumber( + (ISAXLocator*)&This->lpVBSAXLocatorVtbl, + pnLine); +} - HeapFree(GetProcessHeap(), 0, wszError); +static HRESULT WINAPI ivbsaxlocator_get_publicId( + IVBSAXLocator* iface, + BSTR* publicId) +{ + saxlocator *This = impl_from_IVBSAXLocator( iface ); + return ISAXLocator_getPublicId( + (ISAXLocator*)&This->lpVBSAXLocatorVtbl, + (const WCHAR**)publicId); +} - xmlStopParser(This->pParserCtxt); - This->ret = E_FAIL; +static HRESULT WINAPI ivbsaxlocator_get_systemId( + IVBSAXLocator* iface, + BSTR* systemId) +{ + saxlocator *This = impl_from_IVBSAXLocator( iface ); + return ISAXLocator_getSystemId( + (ISAXLocator*)&This->lpVBSAXLocatorVtbl, + (const WCHAR**)systemId); } +static const struct IVBSAXLocatorVtbl ivbsaxlocator_vtbl = +{ + ivbsaxlocator_QueryInterface, + ivbsaxlocator_AddRef, + ivbsaxlocator_Release, + ivbsaxlocator_GetTypeInfoCount, + ivbsaxlocator_GetTypeInfo, + ivbsaxlocator_GetIDsOfNames, + ivbsaxlocator_Invoke, + ivbsaxlocator_get_columnNumber, + ivbsaxlocator_get_lineNumber, + ivbsaxlocator_get_publicId, + ivbsaxlocator_get_systemId +}; + /*** ISAXLocator interface ***/ /*** IUnknown methods ***/ static HRESULT WINAPI isaxlocator_QueryInterface(ISAXLocator* iface, REFIID riid, void **ppvObject) @@ -456,77 +1396,381 @@ static HRESULT WINAPI isaxlocator_getPublicId( if(This->publicId) SysFreeString(This->publicId); - publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt)); - if(SysStringLen(publicId)) - This->publicId = (WCHAR*)&publicId; - else - { - SysFreeString(publicId); - This->publicId = NULL; + publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt)); + if(SysStringLen(publicId)) + This->publicId = (WCHAR*)&publicId; + else + { + SysFreeString(publicId); + This->publicId = NULL; + } + + *ppwchPublicId = This->publicId; + return S_OK; +} + +static HRESULT WINAPI isaxlocator_getSystemId( + ISAXLocator* iface, + const WCHAR ** ppwchSystemId) +{ + BSTR systemId; + saxlocator *This = impl_from_ISAXLocator( iface ); + + if(This->systemId) SysFreeString(This->systemId); + + systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt)); + if(SysStringLen(systemId)) + This->systemId = (WCHAR*)&systemId; + else + { + SysFreeString(systemId); + This->systemId = NULL; + } + + *ppwchSystemId = This->systemId; + return S_OK; +} + +static const struct ISAXLocatorVtbl isaxlocator_vtbl = +{ + isaxlocator_QueryInterface, + isaxlocator_AddRef, + isaxlocator_Release, + isaxlocator_getColumnNumber, + isaxlocator_getLineNumber, + isaxlocator_getPublicId, + isaxlocator_getSystemId +}; + +static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, BOOL vbInterface) +{ + saxlocator *locator; + + locator = HeapAlloc( GetProcessHeap(), 0, sizeof (*locator) ); + if( !locator ) + return E_OUTOFMEMORY; + + locator->lpVBSAXLocatorVtbl = &ivbsaxlocator_vtbl; + locator->lpSAXLocatorVtbl = &isaxlocator_vtbl; + locator->ref = 1; + locator->vbInterface = vbInterface; + + locator->saxreader = reader; + ISAXXMLReader_AddRef((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl); + + locator->pParserCtxt = NULL; + locator->publicId = NULL; + locator->systemId = NULL; + locator->lastCur = NULL; + locator->line = 0; + locator->column = 0; + locator->ret = S_OK; + + *ppsaxlocator = locator; + + TRACE("returning %p\n", *ppsaxlocator); + + return S_OK; +} + +/*** SAXXMLReader internal functions ***/ +static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int size, BOOL vbInterface) +{ + saxlocator *locator; + HRESULT hr; + + hr = SAXLocator_create(This, &locator, vbInterface); + if(FAILED(hr)) + return E_FAIL; + + locator->pParserCtxt = xmlCreateMemoryParserCtxt(buffer, size); + if(!locator->pParserCtxt) + { + ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl); + return E_FAIL; + } + + locator->pParserCtxt->sax = &locator->saxreader->sax; + locator->pParserCtxt->userData = locator; + + if(xmlParseDocument(locator->pParserCtxt)) hr = E_FAIL; + else hr = locator->ret; + + if(locator->pParserCtxt) + { + locator->pParserCtxt->sax = NULL; + xmlFreeParserCtxt(locator->pParserCtxt); + locator->pParserCtxt = NULL; + } + + ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl); + return S_OK; +} + +static HRESULT WINAPI internal_getEntityResolver( + saxreader *This, + void *pEntityResolver, + BOOL vbInterface) +{ + FIXME("(%p)->(%p) stub\n", This, pEntityResolver); + return E_NOTIMPL; +} + +static HRESULT WINAPI internal_putEntityResolver( + saxreader *This, + void *pEntityResolver, + BOOL vbInterface) +{ + FIXME("(%p)->(%p) stub\n", This, pEntityResolver); + return E_NOTIMPL; +} + +static HRESULT WINAPI internal_getContentHandler( + saxreader* This, + void *pContentHandler, + BOOL vbInterface) +{ + TRACE("(%p)->(%p)\n", This, pContentHandler); + if(pContentHandler == NULL) + return E_POINTER; + if(This->contentHandler) + { + if(vbInterface) + IVBSAXContentHandler_AddRef(This->vbcontentHandler); + else + ISAXContentHandler_AddRef(This->contentHandler); + } + if(vbInterface) *(IVBSAXContentHandler**)pContentHandler = + This->vbcontentHandler; + else *(ISAXContentHandler**)pContentHandler = This->contentHandler; + + return S_OK; +} + +static HRESULT WINAPI internal_putContentHandler( + saxreader* This, + void *contentHandler, + BOOL vbInterface) +{ + TRACE("(%p)->(%p)\n", This, contentHandler); + if(contentHandler) + { + if(vbInterface) + IVBSAXContentHandler_AddRef((IVBSAXContentHandler*)contentHandler); + else + ISAXContentHandler_AddRef((ISAXContentHandler*)contentHandler); + } + if(This->contentHandler) + { + if(vbInterface) + IVBSAXContentHandler_Release(This->vbcontentHandler); + else + ISAXContentHandler_Release(This->contentHandler); + } + if(vbInterface) + This->vbcontentHandler = contentHandler; + else + This->contentHandler = contentHandler; + + return S_OK; +} + +static HRESULT WINAPI internal_getDTDHandler( + saxreader* This, + void *pDTDHandler, + BOOL vbInterface) +{ + FIXME("(%p)->(%p) stub\n", This, pDTDHandler); + return E_NOTIMPL; +} + +static HRESULT WINAPI internal_putDTDHandler( + saxreader* This, + void *pDTDHandler, + BOOL vbInterface) +{ + FIXME("(%p)->(%p) stub\n", This, pDTDHandler); + return E_NOTIMPL; +} + +static HRESULT WINAPI internal_getErrorHandler( + saxreader* This, + void *pErrorHandler, + BOOL vbInterface) +{ + TRACE("(%p)->(%p)\n", This, pErrorHandler); + if(pErrorHandler == NULL) + return E_POINTER; + if(This->errorHandler) + { + if(vbInterface) + IVBSAXErrorHandler_AddRef(This->vberrorHandler); + else + ISAXErrorHandler_AddRef(This->errorHandler); + } + if(vbInterface) + *(IVBSAXErrorHandler**)pErrorHandler = This->vberrorHandler; + else + *(ISAXErrorHandler**)pErrorHandler = This->errorHandler; + + return S_OK; + +} + +static HRESULT WINAPI internal_putErrorHandler( + saxreader* This, + void *errorHandler, + BOOL vbInterface) +{ + TRACE("(%p)->(%p)\n", This, errorHandler); + if(errorHandler) + { + if(vbInterface) + IVBSAXErrorHandler_AddRef((IVBSAXErrorHandler*)errorHandler); + else + ISAXErrorHandler_AddRef((ISAXErrorHandler*)errorHandler); + } + if(This->errorHandler) + { + if(vbInterface) + IVBSAXErrorHandler_Release(This->vberrorHandler); + else + ISAXErrorHandler_Release(This->errorHandler); + } + if(vbInterface) + This->vberrorHandler = errorHandler; + else + This->errorHandler = errorHandler; + + return S_OK; + +} + +static HRESULT WINAPI internal_parse( + saxreader* This, + VARIANT varInput, + BOOL vbInterface) +{ + HRESULT hr; + + TRACE("(%p)\n", This); + + hr = S_OK; + switch(V_VT(&varInput)) + { + case VT_BSTR: + hr = internal_parseBuffer(This, (const char*)V_BSTR(&varInput), + SysStringByteLen(V_BSTR(&varInput)), vbInterface); + break; + case VT_ARRAY|VT_UI1: { + void *pSAData; + LONG lBound, uBound; + ULONG dataRead; + + hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound); + if(hr != S_OK) break; + hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound); + if(hr != S_OK) break; + dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput)); + hr = SafeArrayAccessData(V_ARRAY(&varInput), (void**)&pSAData); + if(hr != S_OK) break; + hr = internal_parseBuffer(This, pSAData, dataRead, vbInterface); + SafeArrayUnaccessData(V_ARRAY(&varInput)); + break; + } + case VT_UNKNOWN: + case VT_DISPATCH: { + IPersistStream *persistStream; + IStream *stream = NULL; + IXMLDOMDocument *xmlDoc; + + if(IUnknown_QueryInterface(V_UNKNOWN(&varInput), + &IID_IPersistStream, (void**)&persistStream) == S_OK) + { + hr = IPersistStream_Save(persistStream, stream, TRUE); + IPersistStream_Release(persistStream); + if(hr != S_OK) break; + } + if(stream || IUnknown_QueryInterface(V_UNKNOWN(&varInput), + &IID_IStream, (void**)&stream) == S_OK) + { + STATSTG dataInfo; + ULONG dataRead; + char *data; + + while(1) + { + hr = IStream_Stat(stream, &dataInfo, STATFLAG_NONAME); + if(hr == E_PENDING) continue; + break; + } + data = HeapAlloc(GetProcessHeap(), 0, + dataInfo.cbSize.QuadPart); + while(1) + { + hr = IStream_Read(stream, data, + dataInfo.cbSize.QuadPart, &dataRead); + if(hr == E_PENDING) continue; + break; + } + hr = internal_parseBuffer(This, data, + dataInfo.cbSize.QuadPart, vbInterface); + HeapFree(GetProcessHeap(), 0, data); + IStream_Release(stream); + break; + } + if(IUnknown_QueryInterface(V_UNKNOWN(&varInput), + &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK) + { + BSTR bstrData; + + IXMLDOMDocument_get_xml(xmlDoc, &bstrData); + hr = internal_parseBuffer(This, (const char*)bstrData, + SysStringByteLen(bstrData), vbInterface); + IXMLDOMDocument_Release(xmlDoc); + hr = E_NOTIMPL; + break; + } + } + default: + WARN("vt %d not implemented\n", V_VT(&varInput)); + hr = E_INVALIDARG; } - *ppwchPublicId = This->publicId; - return S_OK; + return hr; } -static HRESULT WINAPI isaxlocator_getSystemId( - ISAXLocator* iface, - const WCHAR ** ppwchSystemId) +static HRESULT internal_vbonDataAvailable(void *obj, char *ptr, DWORD len) { - BSTR systemId; - saxlocator *This = impl_from_ISAXLocator( iface ); - - if(This->systemId) SysFreeString(This->systemId); - - systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt)); - if(SysStringLen(systemId)) - This->systemId = (WCHAR*)&systemId; - else - { - SysFreeString(systemId); - This->systemId = NULL; - } + saxreader *This = obj; - *ppwchSystemId = This->systemId; - return S_OK; + return internal_parseBuffer(This, ptr, len, TRUE); } -static const struct ISAXLocatorVtbl isaxlocator_vtbl = -{ - isaxlocator_QueryInterface, - isaxlocator_AddRef, - isaxlocator_Release, - isaxlocator_getColumnNumber, - isaxlocator_getLineNumber, - isaxlocator_getPublicId, - isaxlocator_getSystemId -}; - -static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator) +static HRESULT internal_onDataAvailable(void *obj, char *ptr, DWORD len) { - saxlocator *locator; + saxreader *This = obj; - locator = HeapAlloc( GetProcessHeap(), 0, sizeof (*locator) ); - if( !locator ) - return E_OUTOFMEMORY; + return internal_parseBuffer(This, ptr, len, FALSE); +} - locator->lpSAXLocatorVtbl = &isaxlocator_vtbl; - locator->ref = 1; +static HRESULT WINAPI internal_parseURL( + saxreader* This, + const WCHAR *url, + BOOL vbInterface) +{ + bsc_t *bsc; + HRESULT hr; - locator->saxreader = reader; - ISAXXMLReader_AddRef((ISAXXMLReader*)&reader->lpSAXXMLReaderVtbl); + TRACE("(%p)->(%s)\n", This, debugstr_w(url)); - locator->pParserCtxt = NULL; - locator->publicId = NULL; - locator->systemId = NULL; - locator->lastCur = NULL; - locator->line = 0; - locator->column = 0; - locator->ret = S_OK; + if(vbInterface) hr = bind_url(url, internal_vbonDataAvailable, This, &bsc); + else hr = bind_url(url, internal_onDataAvailable, This, &bsc); - *ppsaxlocator = locator; + if(FAILED(hr)) + return hr; - TRACE("returning %p\n", *ppsaxlocator); + detach_bsc(bsc); return S_OK; } @@ -666,7 +1910,7 @@ static HRESULT WINAPI saxxmlreader_Invoke( hr = get_typeinfo(IVBSAXXMLReader_tid, &typeinfo); if(SUCCEEDED(hr)) { - hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams, + hr = ITypeInfo_Invoke(typeinfo, &(This->lpVBSAXXMLReaderVtbl), dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); ITypeInfo_Release(typeinfo); } @@ -724,9 +1968,7 @@ static HRESULT WINAPI saxxmlreader_getEntityResolver( IVBSAXEntityResolver **pEntityResolver) { saxreader *This = impl_from_IVBSAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, pEntityResolver); - return E_NOTIMPL; + return internal_getEntityResolver(This, pEntityResolver, TRUE); } static HRESULT WINAPI saxxmlreader_putEntityResolver( @@ -734,9 +1976,7 @@ static HRESULT WINAPI saxxmlreader_putEntityResolver( IVBSAXEntityResolver *pEntityResolver) { saxreader *This = impl_from_IVBSAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, pEntityResolver); - return E_NOTIMPL; + return internal_putEntityResolver(This, pEntityResolver, TRUE); } static HRESULT WINAPI saxxmlreader_getContentHandler( @@ -744,9 +1984,7 @@ static HRESULT WINAPI saxxmlreader_getContentHandler( IVBSAXContentHandler **ppContentHandler) { saxreader *This = impl_from_IVBSAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, ppContentHandler); - return E_NOTIMPL; + return internal_getContentHandler(This, ppContentHandler, TRUE); } static HRESULT WINAPI saxxmlreader_putContentHandler( @@ -754,9 +1992,7 @@ static HRESULT WINAPI saxxmlreader_putContentHandler( IVBSAXContentHandler *contentHandler) { saxreader *This = impl_from_IVBSAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, contentHandler); - return E_NOTIMPL; + return internal_putContentHandler(This, contentHandler, TRUE); } static HRESULT WINAPI saxxmlreader_getDTDHandler( @@ -764,9 +2000,7 @@ static HRESULT WINAPI saxxmlreader_getDTDHandler( IVBSAXDTDHandler **pDTDHandler) { saxreader *This = impl_from_IVBSAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, pDTDHandler); - return E_NOTIMPL; + return internal_getDTDHandler(This, pDTDHandler, TRUE); } static HRESULT WINAPI saxxmlreader_putDTDHandler( @@ -774,9 +2008,7 @@ static HRESULT WINAPI saxxmlreader_putDTDHandler( IVBSAXDTDHandler *pDTDHandler) { saxreader *This = impl_from_IVBSAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, pDTDHandler); - return E_NOTIMPL; + return internal_putDTDHandler(This, pDTDHandler, TRUE); } static HRESULT WINAPI saxxmlreader_getErrorHandler( @@ -784,9 +2016,7 @@ static HRESULT WINAPI saxxmlreader_getErrorHandler( IVBSAXErrorHandler **pErrorHandler) { saxreader *This = impl_from_IVBSAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, pErrorHandler); - return E_NOTIMPL; + return internal_getErrorHandler(This, pErrorHandler, TRUE); } static HRESULT WINAPI saxxmlreader_putErrorHandler( @@ -794,9 +2024,7 @@ static HRESULT WINAPI saxxmlreader_putErrorHandler( IVBSAXErrorHandler *errorHandler) { saxreader *This = impl_from_IVBSAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, errorHandler); - return E_NOTIMPL; + return internal_putErrorHandler(This, errorHandler, TRUE); } static HRESULT WINAPI saxxmlreader_getBaseURL( @@ -845,9 +2073,7 @@ static HRESULT WINAPI saxxmlreader_parse( VARIANT varInput) { saxreader *This = impl_from_IVBSAXXMLReader( iface ); - - FIXME("(%p) stub\n", This); - return E_NOTIMPL; + return internal_parse(This, varInput, TRUE); } static HRESULT WINAPI saxxmlreader_parseURL( @@ -855,9 +2081,7 @@ static HRESULT WINAPI saxxmlreader_parseURL( const WCHAR *url) { saxreader *This = impl_from_IVBSAXXMLReader( iface ); - - FIXME("(%p)->(%s) stub\n", This, debugstr_w(url)); - return E_NOTIMPL; + return internal_parseURL(This, url, TRUE); } static const struct IVBSAXXMLReaderVtbl saxreader_vtbl = @@ -894,19 +2118,19 @@ static const struct IVBSAXXMLReaderVtbl saxreader_vtbl = static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject) { saxreader *This = impl_from_ISAXXMLReader( iface ); - return saxxmlreader_QueryInterface((IVBSAXXMLReader*)&This->lpVtbl, riid, ppvObject); + return saxxmlreader_QueryInterface((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, riid, ppvObject); } static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface) { saxreader *This = impl_from_ISAXXMLReader( iface ); - return saxxmlreader_AddRef((IVBSAXXMLReader*)&This->lpVtbl); + return saxxmlreader_AddRef((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl); } static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface) { saxreader *This = impl_from_ISAXXMLReader( iface ); - return saxxmlreader_Release((IVBSAXXMLReader*)&This->lpVtbl); + return saxxmlreader_Release((IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl); } /*** ISAXXMLReader methods ***/ @@ -916,9 +2140,9 @@ static HRESULT WINAPI isaxxmlreader_getFeature( VARIANT_BOOL *pValue) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pFeature), pValue); - return E_NOTIMPL; + return IVBSAXXMLReader_getFeature( + (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, + pFeature, pValue); } static HRESULT WINAPI isaxxmlreader_putFeature( @@ -927,9 +2151,9 @@ static HRESULT WINAPI isaxxmlreader_putFeature( VARIANT_BOOL vfValue) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(pFeature), vfValue); - return E_NOTIMPL; + return IVBSAXXMLReader_putFeature( + (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, + pFeature, vfValue); } static HRESULT WINAPI isaxxmlreader_getProperty( @@ -938,9 +2162,9 @@ static HRESULT WINAPI isaxxmlreader_getProperty( VARIANT *pValue) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(pProp), pValue); - return E_NOTIMPL; + return IVBSAXXMLReader_getProperty( + (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, + pProp, pValue); } static HRESULT WINAPI isaxxmlreader_putProperty( @@ -949,9 +2173,9 @@ static HRESULT WINAPI isaxxmlreader_putProperty( VARIANT value) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%s) stub\n", This, debugstr_w(pProp)); - return E_NOTIMPL; + return IVBSAXXMLReader_putProperty( + (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, + pProp, value); } static HRESULT WINAPI isaxxmlreader_getEntityResolver( @@ -959,9 +2183,7 @@ static HRESULT WINAPI isaxxmlreader_getEntityResolver( ISAXEntityResolver **ppEntityResolver) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, ppEntityResolver); - return E_NOTIMPL; + return internal_getEntityResolver(This, ppEntityResolver, FALSE); } static HRESULT WINAPI isaxxmlreader_putEntityResolver( @@ -969,9 +2191,7 @@ static HRESULT WINAPI isaxxmlreader_putEntityResolver( ISAXEntityResolver *pEntityResolver) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, pEntityResolver); - return E_NOTIMPL; + return internal_putEntityResolver(This, pEntityResolver, FALSE); } static HRESULT WINAPI isaxxmlreader_getContentHandler( @@ -979,15 +2199,7 @@ static HRESULT WINAPI isaxxmlreader_getContentHandler( ISAXContentHandler **pContentHandler) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - TRACE("(%p)->(%p)\n", This, pContentHandler); - if(pContentHandler == NULL) - return E_POINTER; - if(This->contentHandler) - ISAXContentHandler_AddRef(This->contentHandler); - *pContentHandler = This->contentHandler; - - return S_OK; + return internal_getContentHandler(This, pContentHandler, FALSE); } static HRESULT WINAPI isaxxmlreader_putContentHandler( @@ -995,15 +2207,7 @@ static HRESULT WINAPI isaxxmlreader_putContentHandler( ISAXContentHandler *contentHandler) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - TRACE("(%p)->(%p)\n", This, contentHandler); - if(contentHandler) - ISAXContentHandler_AddRef(contentHandler); - if(This->contentHandler) - ISAXContentHandler_Release(This->contentHandler); - This->contentHandler = contentHandler; - - return S_OK; + return internal_putContentHandler(This, contentHandler, FALSE); } static HRESULT WINAPI isaxxmlreader_getDTDHandler( @@ -1011,9 +2215,7 @@ static HRESULT WINAPI isaxxmlreader_getDTDHandler( ISAXDTDHandler **pDTDHandler) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, pDTDHandler); - return E_NOTIMPL; + return internal_getDTDHandler(This, pDTDHandler, FALSE); } static HRESULT WINAPI isaxxmlreader_putDTDHandler( @@ -1021,9 +2223,7 @@ static HRESULT WINAPI isaxxmlreader_putDTDHandler( ISAXDTDHandler *pDTDHandler) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, pDTDHandler); - return E_NOTIMPL; + return internal_putDTDHandler(This, pDTDHandler, FALSE); } static HRESULT WINAPI isaxxmlreader_getErrorHandler( @@ -1031,15 +2231,7 @@ static HRESULT WINAPI isaxxmlreader_getErrorHandler( ISAXErrorHandler **pErrorHandler) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - TRACE("(%p)->(%p)\n", This, pErrorHandler); - if(pErrorHandler == NULL) - return E_POINTER; - if(This->errorHandler) - ISAXErrorHandler_AddRef(This->errorHandler); - *pErrorHandler = This->errorHandler; - - return S_OK; + return internal_getErrorHandler(This, pErrorHandler, FALSE); } static HRESULT WINAPI isaxxmlreader_putErrorHandler( @@ -1047,15 +2239,7 @@ static HRESULT WINAPI isaxxmlreader_putErrorHandler( ISAXErrorHandler *errorHandler) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - TRACE("(%p)->(%p)\n", This, errorHandler); - if(errorHandler) - ISAXErrorHandler_AddRef(errorHandler); - if(This->errorHandler) - ISAXErrorHandler_Release(This->errorHandler); - This->errorHandler = errorHandler; - - return S_OK; + return internal_putErrorHandler(This, errorHandler, FALSE); } static HRESULT WINAPI isaxxmlreader_getBaseURL( @@ -1063,9 +2247,9 @@ static HRESULT WINAPI isaxxmlreader_getBaseURL( const WCHAR **pBaseUrl) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, pBaseUrl); - return E_NOTIMPL; + return IVBSAXXMLReader_get_getBaseURL( + (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, + pBaseUrl); } static HRESULT WINAPI isaxxmlreader_putBaseURL( @@ -1073,9 +2257,9 @@ static HRESULT WINAPI isaxxmlreader_putBaseURL( const WCHAR *pBaseUrl) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl)); - return E_NOTIMPL; + return IVBSAXXMLReader_put_putBaseURL( + (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, + pBaseUrl); } static HRESULT WINAPI isaxxmlreader_getSecureBaseURL( @@ -1083,9 +2267,9 @@ static HRESULT WINAPI isaxxmlreader_getSecureBaseURL( const WCHAR **pSecureBaseUrl) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl); - return E_NOTIMPL; + return IVBSAXXMLReader_get_getSecureBaseURL( + (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, + pSecureBaseUrl); } static HRESULT WINAPI isaxxmlreader_putSecureBaseURL( @@ -1093,9 +2277,9 @@ static HRESULT WINAPI isaxxmlreader_putSecureBaseURL( const WCHAR *secureBaseUrl) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl)); - return E_NOTIMPL; + return IVBSAXXMLReader_put_putSecureBaseURL( + (IVBSAXXMLReader*)&This->lpVBSAXXMLReaderVtbl, + secureBaseUrl); } static HRESULT WINAPI isaxxmlreader_parse( @@ -1103,125 +2287,7 @@ static HRESULT WINAPI isaxxmlreader_parse( VARIANT varInput) { saxreader *This = impl_from_ISAXXMLReader( iface ); - saxlocator *locator; - xmlChar *data = NULL; - HRESULT hr; - - TRACE("(%p)\n", This); - - hr = SAXLocator_create(This, &locator); - if(FAILED(hr)) - return E_FAIL; - - locator->pParserCtxt = xmlNewParserCtxt(); - if(!locator->pParserCtxt) - { - ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl); - return E_FAIL; - } - - locator->pParserCtxt->sax = &locator->saxreader->sax; - locator->pParserCtxt->userData = locator; - - hr = S_OK; - switch(V_VT(&varInput)) - { - case VT_BSTR: - data = xmlChar_from_wchar(V_BSTR(&varInput)); - xmlSetupParserForBuffer(locator->pParserCtxt, data, NULL); - break; - case VT_ARRAY|VT_UI1: { - void *pSAData; - LONG lBound, uBound; - ULONG dataRead; - - hr = SafeArrayGetLBound(V_ARRAY(&varInput), 1, &lBound); - if(hr != S_OK) break; - hr = SafeArrayGetUBound(V_ARRAY(&varInput), 1, &uBound); - if(hr != S_OK) break; - dataRead = (uBound-lBound)*SafeArrayGetElemsize(V_ARRAY(&varInput)); - data = HeapAlloc(GetProcessHeap(), 0, dataRead+1); - if(!data) break; - hr = SafeArrayAccessData(V_ARRAY(&varInput), (void**)&pSAData); - if(hr != S_OK) break; - memcpy(data, pSAData, dataRead); - data[dataRead] = '\0'; - xmlSetupParserForBuffer(locator->pParserCtxt, data, NULL); - SafeArrayUnaccessData(V_ARRAY(&varInput)); - break; - } - case VT_UNKNOWN: - case VT_DISPATCH: { - IPersistStream *persistStream; - IStream *stream = NULL; - IXMLDOMDocument *xmlDoc; - - if(IUnknown_QueryInterface(V_UNKNOWN(&varInput), - &IID_IPersistStream, (void**)&persistStream) == S_OK) - { - hr = IPersistStream_Save(persistStream, stream, TRUE); - IPersistStream_Release(persistStream); - if(hr != S_OK) break; - } - if(stream || IUnknown_QueryInterface(V_UNKNOWN(&varInput), - &IID_IStream, (void**)&stream) == S_OK) - { - STATSTG dataInfo; - ULONG dataRead; - - while(1) - { - hr = IStream_Stat(stream, &dataInfo, STATFLAG_NONAME); - if(hr == E_PENDING) continue; - break; - } - data = HeapAlloc(GetProcessHeap(), 0, - dataInfo.cbSize.QuadPart+1); - while(1) - { - hr = IStream_Read(stream, data, - dataInfo.cbSize.QuadPart, &dataRead); - if(hr == E_PENDING) continue; - break; - } - data[dataInfo.cbSize.QuadPart] = '\0'; - xmlSetupParserForBuffer(locator->pParserCtxt, data, NULL); - IStream_Release(stream); - break; - } - if(IUnknown_QueryInterface(V_UNKNOWN(&varInput), - &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK) - { - BSTR bstrData; - - IXMLDOMDocument_get_xml(xmlDoc, &bstrData); - data = xmlChar_from_wchar(bstrData); - xmlSetupParserForBuffer(locator->pParserCtxt, data, NULL); - IXMLDOMDocument_Release(xmlDoc); - hr = E_NOTIMPL; - break; - } - } - default: - WARN("vt %d not implemented\n", V_VT(&varInput)); - hr = E_INVALIDARG; - } - - if(hr == S_OK) - { - if(xmlParseDocument(locator->pParserCtxt)) hr = E_FAIL; - else hr = locator->ret; - } - - if(locator->pParserCtxt) - { - locator->pParserCtxt->sax = NULL; - xmlFreeParserCtxt(locator->pParserCtxt); - locator->pParserCtxt = NULL; - } - HeapFree(GetProcessHeap(), 0, data); - ISAXLocator_Release((ISAXLocator*)&locator->lpSAXLocatorVtbl); - return hr; + return internal_parse(This, varInput, FALSE); } static HRESULT WINAPI isaxxmlreader_parseURL( @@ -1229,9 +2295,7 @@ static HRESULT WINAPI isaxxmlreader_parseURL( const WCHAR *url) { saxreader *This = impl_from_ISAXXMLReader( iface ); - - FIXME("(%p)->(%s) stub\n", This, debugstr_w(url)); - return E_NOTIMPL; + return internal_parseURL(This, url, FALSE); } static const struct ISAXXMLReaderVtbl isaxreader_vtbl = @@ -1269,7 +2333,7 @@ HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj) if( !reader ) return E_OUTOFMEMORY; - reader->lpVtbl = &saxreader_vtbl; + reader->lpVBSAXXMLReaderVtbl = &saxreader_vtbl; reader->lpSAXXMLReaderVtbl = &isaxreader_vtbl; reader->ref = 1; reader->contentHandler = NULL; @@ -1286,7 +2350,7 @@ HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj) reader->sax.error = libxmlFatalError; reader->sax.fatalError = libxmlFatalError; - *ppObj = &reader->lpVtbl; + *ppObj = &reader->lpVBSAXXMLReaderVtbl; TRACE("returning iface %p\n", *ppObj); diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index 1a2f85ca6a2..8d64804adc7 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -3419,6 +3419,44 @@ static void test_Namespaces(void) free_bstrs(); } +static void test_FormattingXML(void) +{ + IXMLDOMDocument2 *doc = NULL; + IXMLDOMElement *pElement; + VARIANT_BOOL bSucc; + HRESULT hr; + BSTR str; + static const CHAR szLinefeedXML[] = "\n\n\t\n"; + static const CHAR szLinefeedRootXML[] = "\r\n\t\r\n"; + + hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (LPVOID*)&doc ); + if( hr != S_OK ) + return; + + hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szLinefeedXML), &bSucc); + ok(hr == S_OK, "ret %08x\n", hr ); + ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n"); + + if(bSucc == VARIANT_TRUE) + { + hr = IXMLDOMDocument2_get_documentElement(doc, &pElement); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + hr = IXMLDOMElement_get_xml(pElement, &str); + ok(hr == S_OK, "ret %08x\n", hr ); + ok( !lstrcmpW( str, _bstr_(szLinefeedRootXML) ), "incorrect element xml\n"); + SysFreeString(str); + + IXMLDOMElement_Release(pElement); + } + } + + IXMLDOMDocument2_Release(doc); + + free_bstrs(); +} + START_TEST(domdoc) { HRESULT r; @@ -3444,6 +3482,7 @@ START_TEST(domdoc) test_DocumentSaveToFile(); test_testTransforms(); test_Namespaces(); + test_FormattingXML(); CoUninitialize(); } diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c index dd69e0f376e..0ff0fdf7e7f 100644 --- a/dlls/msxml3/tests/saxreader.c +++ b/dlls/msxml3/tests/saxreader.c @@ -476,6 +476,9 @@ static void test_saxreader(void) ULARGE_INTEGER liSize; LARGE_INTEGER liPos; ULONG bytesWritten; + HANDLE file; + + static const WCHAR testXmlW[] = {'t','e','s','t','.','x','m','l',0}; hr = CoCreateInstance(&CLSID_SAXXMLReader, NULL, CLSCTX_INPROC_SERVER, &IID_ISAXXMLReader, (LPVOID*)&reader); @@ -561,6 +564,18 @@ static void test_saxreader(void) ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); test_expect_call(CH_ENDTEST); + file = CreateFileW(testXmlW, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError()); + WriteFile(file, szTestXML, sizeof(szTestXML)-1, &bytesWritten, NULL); + CloseHandle(file); + + expectCall = contentHandlerTest1; + hr = ISAXXMLReader_parseURL(reader, testXmlW); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + test_expect_call(CH_ENDTEST); + + DeleteFileW(testXmlW); + ISAXXMLReader_Release(reader); } diff --git a/dlls/netapi32/access.c b/dlls/netapi32/access.c index 4fdf60a26b5..5da07a617fd 100644 --- a/dlls/netapi32/access.c +++ b/dlls/netapi32/access.c @@ -689,6 +689,18 @@ NetGetDCName(LPCWSTR servername, LPCWSTR domainname, LPBYTE *bufptr) return NERR_DCNotFound; /* say we can't find a domain controller */ } +/************************************************************ + * NetGroupEnum (NETAPI32.@) + * + */ +NET_API_STATUS WINAPI +NetGroupEnum(LPCWSTR servername, DWORD level, LPBYTE *bufptr, DWORD prefmaxlen, + LPDWORD entriesread, LPDWORD totalentries, LPDWORD resume_handle) +{ + FIXME("(%s, %d, %p, %d, %p, %p, %p) stub!\n", debugstr_w(servername), + level, bufptr, prefmaxlen, entriesread, totalentries, resume_handle); + return ERROR_ACCESS_DENIED; +} /****************************************************************************** * NetUserModalsGet (NETAPI32.@) diff --git a/dlls/netapi32/netapi32.spec b/dlls/netapi32/netapi32.spec index 2750497b4c0..8f1a5446a76 100644 --- a/dlls/netapi32/netapi32.spec +++ b/dlls/netapi32/netapi32.spec @@ -98,7 +98,7 @@ @ stub NetGroupAddUser @ stub NetGroupDel @ stub NetGroupDelUser -@ stub NetGroupEnum +@ stdcall NetGroupEnum(wstr long ptr long ptr ptr ptr) @ stub NetGroupGetInfo @ stub NetGroupGetUsers @ stub NetGroupSetInfo @@ -217,7 +217,7 @@ @ stub NetWkstaTransportAdd @ stub NetWkstaTransportDel @ stdcall NetWkstaTransportEnum (wstr long ptr long ptr ptr ptr) -@ stub NetWkstaUserEnum +@ stdcall NetWkstaUserEnum(wstr long ptr long ptr ptr ptr) @ stdcall NetWkstaUserGetInfo(wstr long ptr) @ stub NetWkstaUserSetInfo @ stdcall NetapipBufferAllocate(long ptr) NetApiBufferAllocate diff --git a/dlls/netapi32/wksta.c b/dlls/netapi32/wksta.c index 6914d028124..85a33689d7f 100644 --- a/dlls/netapi32/wksta.c +++ b/dlls/netapi32/wksta.c @@ -444,6 +444,19 @@ NET_API_STATUS WINAPI NetWkstaUserGetInfo(LMSTR reserved, DWORD level, } /************************************************************ + * NetWkstaUserEnum (NETAPI32.@) + */ +NET_API_STATUS WINAPI +NetWkstaUserEnum(LMSTR servername, DWORD level, LPBYTE* bufptr, + DWORD prefmaxlen, LPDWORD entriesread, + LPDWORD totalentries, LPDWORD resumehandle) +{ + FIXME("(%s, %d, %p, %d, %p, %p, %p): stub!\n", debugstr_w(servername), + level, bufptr, prefmaxlen, entriesread, totalentries, resumehandle); + return ERROR_INVALID_PARAMETER; +} + +/************************************************************ * NetpGetComputerName (NETAPI32.@) */ NET_API_STATUS WINAPI NetpGetComputerName(LPWSTR *Buffer) diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 92e3819800f..fb2c0fdd160 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -586,13 +586,9 @@ static void merge_vm86_pending_flags( EXCEPTION_RECORD *rec ) extern int sigaction_syscall( int sig, const struct sigaction *new, struct sigaction *old ); __ASM_GLOBAL_FUNC( sigaction_syscall, - "call 1f\n" - "1:\tpopl %edx\n\t" "movl $0x62,%eax\n\t" - "add $[2f-1b],%edx\n\t" - "movl %esp,%ecx\n\t" - "sysenter\n" - "2:\tret" ) + "int $0x91\n\t" + "ret" ) /* assume the same libc handler is used for all signals */ static void (*libc_sigacthandler)( int signal, siginfo_t *siginfo, void *context ); diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index a60adfa6573..18baeeee168 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -643,7 +643,7 @@ static inline void queue_move_timer(struct queue_timer *t, ULONGLONG time, static void queue_timer_expire(struct timer_queue *q) { - struct queue_timer *t; + struct queue_timer *t = NULL; RtlEnterCriticalSection(&q->cs); if (list_head(&q->timers)) @@ -656,9 +656,9 @@ static void queue_timer_expire(struct timer_queue *q) t, t->period ? queue_current_time() + t->period : EXPIRE_NEVER, FALSE); } + else + t = NULL; } - else - t = NULL; RtlLeaveCriticalSection(&q->cs); if (t) @@ -816,9 +816,14 @@ NTSTATUS WINAPI RtlDeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) { struct timer_queue *q = TimerQueue; struct queue_timer *t, *temp; - HANDLE thread = q->thread; + HANDLE thread; NTSTATUS status; + if (!q) + return STATUS_INVALID_HANDLE; + + thread = q->thread; + RtlEnterCriticalSection(&q->cs); q->quit = TRUE; if (list_head(&q->timers)) @@ -851,6 +856,31 @@ NTSTATUS WINAPI RtlDeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent) return status; } +static struct timer_queue *default_timer_queue; + +static struct timer_queue *get_timer_queue(HANDLE TimerQueue) +{ + if (TimerQueue) + return TimerQueue; + else + { + if (!default_timer_queue) + { + HANDLE q; + NTSTATUS status = RtlCreateTimerQueue(&q); + if (status == STATUS_SUCCESS) + { + PVOID p = interlocked_cmpxchg_ptr( + (void **) &default_timer_queue, q, NULL); + if (p) + /* Got beat to the punch. */ + RtlDeleteTimerQueueEx(p, NULL); + } + } + return default_timer_queue; + } +} + /*********************************************************************** * RtlCreateTimer (NTDLL.@) * @@ -882,8 +912,12 @@ NTSTATUS WINAPI RtlCreateTimer(PHANDLE NewTimer, HANDLE TimerQueue, ULONG Flags) { NTSTATUS status; - struct timer_queue *q = TimerQueue; - struct queue_timer *t = RtlAllocateHeap(GetProcessHeap(), 0, sizeof *t); + struct queue_timer *t; + struct timer_queue *q = get_timer_queue(TimerQueue); + if (!q) + return STATUS_NO_MEMORY; + + t = RtlAllocateHeap(GetProcessHeap(), 0, sizeof *t); if (!t) return STATUS_NO_MEMORY; @@ -933,8 +967,8 @@ NTSTATUS WINAPI RtlCreateTimer(PHANDLE NewTimer, HANDLE TimerQueue, NTSTATUS WINAPI RtlUpdateTimer(HANDLE TimerQueue, HANDLE Timer, DWORD DueTime, DWORD Period) { - struct timer_queue *q = TimerQueue; struct queue_timer *t = Timer; + struct timer_queue *q = t->q; RtlEnterCriticalSection(&q->cs); /* Can't change a timer if it was once-only or destroyed. */ @@ -969,8 +1003,8 @@ NTSTATUS WINAPI RtlUpdateTimer(HANDLE TimerQueue, HANDLE Timer, NTSTATUS WINAPI RtlDeleteTimer(HANDLE TimerQueue, HANDLE Timer, HANDLE CompletionEvent) { - struct timer_queue *q = TimerQueue; struct queue_timer *t = Timer; + struct timer_queue *q = t->q; NTSTATUS status = STATUS_PENDING; HANDLE event = NULL; diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 564c55b5cd1..aff50fd5487 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -247,6 +247,35 @@ NTSTATUS wine_ntoskrnl_main_loop( HANDLE stop_event ) } } + +/*********************************************************************** + * IoInitializeIrp (NTOSKRNL.EXE.@) + */ +void WINAPI IoInitializeIrp( IRP *irp, USHORT size, CCHAR stack_size ) +{ + FIXME( "%p, %u, %d\n", irp, size, stack_size ); +} + + +/*********************************************************************** + * IoAllocateIrp (NTOSKRNL.EXE.@) + */ +PIRP WINAPI IoAllocateIrp( CCHAR stack_size, BOOLEAN charge_quota ) +{ + FIXME( "%d, %d\n", stack_size, charge_quota ); + return NULL; +} + + +/*********************************************************************** + * IoFreeIrp (NTOSKRNL.EXE.@) + */ +void WINAPI IoFreeIrp( IRP *irp ) +{ + FIXME( "%p\n", irp ); +} + + /*********************************************************************** * IoAllocateMdl (NTOSKRNL.EXE.@) */ @@ -412,6 +441,16 @@ NTSTATUS WINAPI IoCreateSymbolicLink( UNICODE_STRING *name, UNICODE_STRING *targ /*********************************************************************** + * IoDeleteSymbolicLink (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI IoDeleteSymbolicLink( UNICODE_STRING *name ) +{ + FIXME( "%s\n", debugstr_us(name) ); + return STATUS_SUCCESS; +} + + +/*********************************************************************** * IofCompleteRequest (NTOSKRNL.EXE.@) */ #ifdef DEFINE_FASTCALL2_ENTRYPOINT diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 0e7b8e89df3..0bfda7e6685 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -311,7 +311,7 @@ @ stub IoAllocateController @ stub IoAllocateDriverObjectExtension @ stub IoAllocateErrorLogEntry -@ stub IoAllocateIrp +@ stdcall IoAllocateIrp(long long) @ stdcall IoAllocateMdl(ptr long long long ptr) @ stdcall IoAllocateWorkItem(ptr) @ stub IoAssignResources @@ -355,7 +355,7 @@ @ stub IoDeleteController @ stdcall IoDeleteDevice(ptr) @ stdcall IoDeleteDriver(ptr) -@ stub IoDeleteSymbolicLink +@ stdcall IoDeleteSymbolicLink(ptr) @ stub IoDetachDevice @ stub IoDeviceHandlerObjectSize @ stub IoDeviceHandlerObjectType @@ -370,7 +370,7 @@ @ stub IoForwardIrpSynchronously @ stub IoFreeController @ stub IoFreeErrorLogEntry -@ stub IoFreeIrp +@ stdcall IoFreeIrp(ptr) @ stub IoFreeMdl @ stub IoFreeWorkItem @ stub IoGetAttachedDevice @@ -397,7 +397,7 @@ @ stub IoGetRequestorSessionId @ stub IoGetStackLimits @ stub IoGetTopLevelIrp -@ stub IoInitializeIrp +@ stdcall IoInitializeIrp(ptr long long) @ stub IoInitializeRemoveLockEx @ stub IoInitializeTimer @ stub IoInvalidateDeviceRelations diff --git a/dlls/ole32/defaulthandler.c b/dlls/ole32/defaulthandler.c index dda2d4b363c..afacc510dd7 100644 --- a/dlls/ole32/defaulthandler.c +++ b/dlls/ole32/defaulthandler.c @@ -715,7 +715,7 @@ static HRESULT WINAPI DefaultHandler_SetExtent( dwDrawAspect, psizel->cx, psizel->cy); if (object_is_running(This)) - IOleObject_SetExtent(This->pOleDelegate, dwDrawAspect, psizel); + return IOleObject_SetExtent(This->pOleDelegate, dwDrawAspect, psizel); return OLE_E_NOTRUNNING; } diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index 472ab8d2c7d..45c5e13841d 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -2882,7 +2882,7 @@ static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typein return S_OK; } - ERR("Unable to find reference\n"); + ERR_(typelib)("Unable to find reference\n"); *typelib_ref = -1; return E_FAIL; } @@ -3007,7 +3007,7 @@ static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL, name += SLTG_ReadStringA(name, &refname); if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2) - FIXME("Can't sscanf ref\n"); + FIXME_(typelib)("Can't sscanf ref\n"); if(lib_offs != 0xffff) { TLBImpLib **import = &pTL->pImpLibs; @@ -3029,7 +3029,7 @@ static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL, &(*import)->wVersionMajor, &(*import)->wVersionMinor, &(*import)->lcid, fname) != 4) { - FIXME("can't sscanf ref %s\n", + FIXME_(typelib)("can't sscanf ref %s\n", pNameTable + lib_offs + 40); } len = strlen(fname); @@ -3057,7 +3057,7 @@ static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL, typelib_ref += 4; } if((BYTE)*name != SLTG_REF_MAGIC) - FIXME("End of ref block magic = %x\n", *name); + FIXME_(typelib)("End of ref block magic = %x\n", *name); dump_TLBRefType(pTL); return table; } @@ -3086,7 +3086,7 @@ static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI, if(info->next == 0xffff) break; if(OneOnly) - FIXME("Interface inheriting more than one interface\n"); + FIXME_(typelib)("Interface inheriting more than one interface\n"); info = (SLTG_ImplInfo*)(pBlk + info->next); } info++; /* see comment at top of function */ @@ -3135,6 +3135,12 @@ static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsign SLTG_DoElem(pType, pBlk, &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup); + if (TRACE_ON(typelib)) { + char buf[300]; + dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf); + TRACE_(typelib)("elemdescVar: %s\n", buf); + } + if (pItem->flags & 0x40) { TRACE_(typelib)("VAR_DISPATCH\n"); (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH; @@ -3155,9 +3161,15 @@ static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsign case VT_BSTR: { WORD len = *(WORD *)(pBlk + pItem->byte_offs); - INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0); - BSTR str = SysAllocStringLen(NULL, alloc_len); - MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len); + BSTR str; + TRACE_(typelib)("len = %u\n", len); + if (len == 0xffff) { + str = NULL; + } else { + INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0); + str = SysAllocStringLen(NULL, alloc_len); + MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len); + } V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR; V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str; break; @@ -3170,7 +3182,7 @@ static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsign *(INT*)(pBlk + pItem->byte_offs); break; default: - FIXME("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt); + FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt); } } } @@ -3186,12 +3198,6 @@ static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsign if (pItem->flags & 0x80) (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY; - if (TRACE_ON(typelib)) { - char buf[300]; - dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf); - TRACE_(typelib)("elemdescVar: %s\n", buf); - } - bstrPrevName = (*ppVarDesc)->Name; ppVarDesc = &((*ppVarDesc)->next); } @@ -3302,6 +3308,9 @@ static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, if(paramName) { (*ppFuncDesc)->pParamDesc[param].Name = TLB_MultiByteToBSTR(paramName); + } else { + (*ppFuncDesc)->pParamDesc[param].Name = + SysAllocString((*ppFuncDesc)->Name); } } @@ -3439,6 +3448,8 @@ static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI, if (pTITail->funcs_off != 0xffff) SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup); HeapFree(GetProcessHeap(), 0, ref_lookup); + if (TRACE_ON(typelib)) + dump_TypeInfo(pTI); } /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more @@ -3491,7 +3502,7 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic, pHeader->nrOfFileBlks ); if (pHeader->SLTG_magic != SLTG_SIGNATURE) { - FIXME("Header type magic 0x%08x not supported.\n", + FIXME_(typelib)("Header type magic 0x%08x not supported.\n", pHeader->SLTG_magic); return NULL; } @@ -3508,12 +3519,12 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) /* Let's see if we're still in sync */ if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC, sizeof(SLTG_COMPOBJ_MAGIC))) { - FIXME("CompObj magic = %s\n", pMagic->CompObj_magic); + FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic); return NULL; } if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC, sizeof(SLTG_DIR_MAGIC))) { - FIXME("dir magic = %s\n", pMagic->dir_magic); + FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic); return NULL; } @@ -3607,7 +3618,7 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) pNameTable += 0x20; break; default: - FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable); + FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable); break; } @@ -3615,7 +3626,7 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) pNameTable += 2; - TRACE("Library name is %s\n", pNameTable + pLibBlk->name); + TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name); pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name); @@ -3637,16 +3648,17 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) { - FIXME("Index strings don't match\n"); + FIXME_(typelib)("Index strings don't match\n"); return NULL; } pTIHeader = pBlk; if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) { - FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic); + FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic); return NULL; } - TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n", + TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, " + "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n", pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e); *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor(); @@ -3664,11 +3676,11 @@ static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength) (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5); if((pTIHeader->typeflags1 & 7) != 2) - FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1); + FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1); if(pTIHeader->typeflags3 != 2) - FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3); + FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3); - TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n", + TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n", debugstr_w((*ppTypeInfoImpl)->Name), typekind_desc[pTIHeader->typekind], debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid), diff --git a/dlls/qcap/dllsetup.c b/dlls/qcap/dllsetup.c index 6aa14785294..a732b73a9ef 100644 --- a/dlls/qcap/dllsetup.c +++ b/dlls/qcap/dllsetup.c @@ -99,106 +99,6 @@ err_out: } /* - * SetupRegisterFilter through IFilterMapper2 - */ -static HRESULT SetupRegisterFilter2(const AMOVIESETUP_FILTER * const pSetup, - IFilterMapper2 * pIFM2, BOOL bRegister) -{ - HRESULT hr; - - if (NULL == pSetup) - return S_FALSE; - - /* unregister filter */ - hr = IFilterMapper2_UnregisterFilter(pIFM2, 0, 0, pSetup->clsID); - - if (bRegister) - { - REGFILTER2 rf2; - rf2.dwVersion = 1; - rf2.dwMerit = pSetup->dwMerit; - rf2.u.s.cPins = pSetup->nPins; - rf2.u.s.rgPins = pSetup->lpPin; - - /* register filter */ - hr = IFilterMapper2_RegisterFilter(pIFM2, pSetup->clsID, - pSetup->strName, 0, 0, NULL, &rf2); - } - else - { - /* filter not found is ignored here, - but there is no #define for 0x80070002 */ - if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) - hr = NOERROR; - } - return hr; -} - -/* - * SetupRegisterFilter through IFilterMapper - */ -static HRESULT SetupRegisterFilter(const AMOVIESETUP_FILTER * const pSetup, - IFilterMapper * pIFM, BOOL bRegister) -{ - HRESULT hr; - - if (NULL == pSetup) - return S_FALSE; - - /* unregister filter */ - hr = IFilterMapper_UnregisterFilter(pIFM, *pSetup->clsID); - - if (bRegister) - { - /* register filter */ - hr = IFilterMapper_RegisterFilter(pIFM, *pSetup->clsID, - pSetup->strName, pSetup->dwMerit); - if (SUCCEEDED(hr)) - { - const AMOVIESETUP_PIN *lpPin = pSetup->lpPin; - const AMOVIESETUP_MEDIATYPE *lpType; - UINT i, j; - - for (i = 0; i < pSetup->nPins; i++, lpPin++) - { - hr = IFilterMapper_RegisterPin(pIFM, *(pSetup->clsID), - lpPin->strName, - lpPin->bRendered, - lpPin->bOutput, - lpPin->bZero, - lpPin->bMany, - *(lpPin->clsConnectsToFilter), - lpPin->strConnectsToPin); - - if (SUCCEEDED(hr)) - { - lpType = lpPin->lpMediaType; - - /* and each pin's media types */ - for (j = 0; j < lpPin->nMediaTypes; j++, lpType++) - { - hr = IFilterMapper_RegisterPinType(pIFM, *(pSetup->clsID), - lpPin->strName, - *(lpType->clsMajorType), - *(lpType->clsMinorType)); - if (FAILED(hr)) break; - } - if (FAILED(hr)) break; - } - if (FAILED(hr)) break; - } - } - } - else - { - /* filter not registered is ignored here, there is no definition for 0x80070002 */ - if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) - hr = NOERROR; - } - return hr; -} - -/* * RegisterAllClasses() */ static HRESULT SetupRegisterAllClasses(const CFactoryTemplate * pList, int num, @@ -246,7 +146,6 @@ HRESULT SetupRegisterServers(const CFactoryTemplate * pList, int num, static const WCHAR szFileName[] = {'q','c','a','p','.','d','l','l',0}; HRESULT hr = NOERROR; IFilterMapper2 *pIFM2 = NULL; - IFilterMapper *pIFM = NULL; /* first register all server classes, just to make sure */ if (bRegister) @@ -260,13 +159,6 @@ HRESULT SetupRegisterServers(const CFactoryTemplate * pList, int num, TRACE("Getting IFilterMapper2\r\n"); hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (void **)&pIFM2); - if (FAILED(hr)) - { - TRACE("- trying IFilterMapper instead\r\n"); - - hr = CoCreateInstance(&CLSID_FilterMapper, NULL, CLSCTX_INPROC_SERVER, - &IID_IFilterMapper, (void **)&pIFM); - } if (SUCCEEDED(hr)) { @@ -275,14 +167,9 @@ HRESULT SetupRegisterServers(const CFactoryTemplate * pList, int num, /* scan through array of CFactoryTemplates registering all filters */ for (i = 0; i < num; i++, pList++) { - if (NULL != pList->m_pAMovieSetup_Filter) + if (pList->m_pAMovieSetup_Filter.dwVersion) { - if (pIFM2) - hr = SetupRegisterFilter2(pList->m_pAMovieSetup_Filter, - pIFM2, bRegister); - else - hr = SetupRegisterFilter(pList->m_pAMovieSetup_Filter, - pIFM, bRegister); + hr = IFilterMapper2_RegisterFilter(pIFM2, pList->m_ClsID, pList->m_Name, NULL, &CLSID_LegacyAmFilterCategory, NULL, &pList->m_pAMovieSetup_Filter); } /* check final error for this pass and break loop if we failed */ @@ -291,10 +178,7 @@ HRESULT SetupRegisterServers(const CFactoryTemplate * pList, int num, } /* release interface */ - if (pIFM2) - IFilterMapper2_Release(pIFM2); - else - IFilterMapper_Release(pIFM); + IFilterMapper2_Release(pIFM2); } /* and clear up */ diff --git a/dlls/qcap/dllsetup.h b/dlls/qcap/dllsetup.h index 4b587ac6645..d582b740513 100644 --- a/dlls/qcap/dllsetup.h +++ b/dlls/qcap/dllsetup.h @@ -35,15 +35,6 @@ typedef REGFILTERPINS AMOVIESETUP_PIN, * PAMOVIESETUP_PIN, * LPAMOVIESETUP_PIN; -typedef struct _AMOVIESETUP_FILTER -{ - const CLSID *clsID; - const WCHAR *strName; - DWORD dwMerit; - UINT nPins; - const AMOVIESETUP_PIN *lpPin; -} AMOVIESETUP_FILTER, * PAMOVIESETUP_FILTER, * LPAMOVIESETUP_FILTER; - /* This needs to go into Combase.h */ typedef IUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr); typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid); @@ -53,7 +44,7 @@ typedef struct tagCFactoryTemplate { const CLSID *m_ClsID; LPFNNewCOMObject m_lpfnNew; LPFNInitRoutine m_lpfnInit; - const AMOVIESETUP_FILTER *m_pAMovieSetup_Filter; + const REGFILTER2 m_pAMovieSetup_Filter; } CFactoryTemplate; /**************************************************************************** diff --git a/dlls/qcap/qcap_main.c b/dlls/qcap/qcap_main.c index 0d29f58aaf4..e5c9e3b55a4 100644 --- a/dlls/qcap/qcap_main.c +++ b/dlls/qcap/qcap_main.c @@ -83,79 +83,66 @@ static CFactoryTemplate const g_cTemplates[] = { wAudioCaptureFilter, &CLSID_AudioCaptureFilter, QCAP_createAudioCaptureFilter, - NULL, NULL },{ wAVICompressor, &CLSID_AVICompressor, QCAP_createAVICompressor, - NULL, NULL },*/{ wVFWCaptFilter, &CLSID_VfwCapture, QCAP_createVFWCaptureFilter, - NULL, NULL },/*{ wVFWCaptFilterProp, &CLSID_VFWCaptureFilterPropertyPage, QCAP_createVFWCaptureFilterPropertyPage, - NULL, NULL },{ wAVIMux, &CLSID_AVImux, QCAP_createAVImux, - NULL, NULL },{ wAVIMuxPropPage, &CLSID_AVImuxPropertyPage, QCAP_createAVImuxPropertyPage, - NULL, NULL },{ wAVIMuxPropPage1, &CLSID_AVImuxPropertyPage1, QCAP_createAVImuxPropertyPage1, - NULL, NULL },{ wFileWriter, &CLSID_FileWriter, QCAP_createFileWriter, - NULL, NULL },*/{ wCaptGraphBuilder, &CLSID_CaptureGraphBuilder, QCAP_createCaptureGraphBuilder2, - NULL, NULL },{ wCaptGraphBuilder2, &CLSID_CaptureGraphBuilder2, QCAP_createCaptureGraphBuilder2, - NULL, NULL }/*,{ wInfPinTeeFilter, &CLSID_InfinitePinTeeFilter, QCAP_createInfinitePinTeeFilter, - NULL, NULL },{ wSmartTeeFilter, &CLSID_SmartTeeFilter, QCAP_createSmartTeeFilter, - NULL, NULL },{ wAudioInMixerProp, &CLSID_AudioInputMixerPropertyPage, QCAP_createAudioInputMixerPropertyPage, - NULL, NULL }*/ }; diff --git a/dlls/quartz/acmwrapper.c b/dlls/quartz/acmwrapper.c index 2dc49da917a..f395f823626 100644 --- a/dlls/quartz/acmwrapper.c +++ b/dlls/quartz/acmwrapper.c @@ -52,9 +52,9 @@ typedef struct ACMWrapperImpl LONGLONG lasttime_sent; } ACMWrapperImpl; -static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilter, IMediaSample *pSample) +static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample) { - ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter; + ACMWrapperImpl* This = (ACMWrapperImpl*)pin->pin.pinInfo.pFilter; AM_MEDIA_TYPE amt; IMediaSample* pOutSample = NULL; DWORD cbDstStream, cbSrcStream; @@ -65,18 +65,17 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte MMRESULT res; HRESULT hr; LONGLONG tStart = -1, tStop = -1, tMed; - InputPin *pin = (InputPin *)pTransformFilter->ppPins[0]; - EnterCriticalSection(&pTransformFilter->csFilter); - if (pTransformFilter->state == State_Stopped) + EnterCriticalSection(&This->tf.csFilter); + if (This->tf.state == State_Stopped) { - LeaveCriticalSection(&pTransformFilter->csFilter); + LeaveCriticalSection(&This->tf.csFilter); return VFW_E_WRONG_STATE; } if (pin->end_of_stream || pin->flushing) { - LeaveCriticalSection(&pTransformFilter->csFilter); + LeaveCriticalSection(&This->tf.csFilter); return S_FALSE; } @@ -84,7 +83,7 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte if (FAILED(hr)) { ERR("Cannot get pointer to sample data (%x)\n", hr); - LeaveCriticalSection(&pTransformFilter->csFilter); + LeaveCriticalSection(&This->tf.csFilter); return hr; } @@ -112,7 +111,7 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte if (FAILED(hr)) { ERR("Unable to retrieve media type\n"); - LeaveCriticalSection(&pTransformFilter->csFilter); + LeaveCriticalSection(&This->tf.csFilter); return hr; } @@ -125,7 +124,7 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte if (FAILED(hr)) { ERR("Unable to get delivery buffer (%x)\n", hr); - LeaveCriticalSection(&pTransformFilter->csFilter); + LeaveCriticalSection(&This->tf.csFilter); return hr; } IMediaSample_SetPreroll(pOutSample, preroll); @@ -231,13 +230,13 @@ error: This->lasttime_real = tStop; This->lasttime_sent = tMed; - LeaveCriticalSection(&pTransformFilter->csFilter); + LeaveCriticalSection(&This->tf.csFilter); return hr; } -static HRESULT ACMWrapper_ConnectInput(TransformFilterImpl* pTransformFilter, const AM_MEDIA_TYPE * pmt) +static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) { - ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter; + ACMWrapperImpl* This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter; MMRESULT res; TRACE("(%p)->(%p)\n", This, pmt); @@ -287,14 +286,14 @@ static HRESULT ACMWrapper_ConnectInput(TransformFilterImpl* pTransformFilter, co return VFW_E_TYPE_NOT_ACCEPTED; } -static HRESULT ACMWrapper_Cleanup(TransformFilterImpl* pTransformFilter) +static HRESULT ACMWrapper_Cleanup(InputPin *pin) { - ACMWrapperImpl* This = (ACMWrapperImpl*)pTransformFilter; + ACMWrapperImpl *This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter; TRACE("(%p)->()\n", This); - + if (This->has) - acmStreamClose(This->has, 0); + acmStreamClose(This->has, 0); This->has = 0; This->lasttime_real = This->lasttime_sent = -1; diff --git a/dlls/quartz/avidec.c b/dlls/quartz/avidec.c index 476e0d36918..ae95cf5d4fd 100644 --- a/dlls/quartz/avidec.c +++ b/dlls/quartz/avidec.c @@ -42,8 +42,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); -static HRESULT AVIDec_Cleanup(TransformFilterImpl* pTransformFilter); - typedef struct AVIDecImpl { TransformFilterImpl tf; @@ -68,9 +66,9 @@ static HRESULT AVIDec_ProcessBegin(TransformFilterImpl* pTransformFilter) return S_OK; } -static HRESULT AVIDec_ProcessSampleData(TransformFilterImpl* pTransformFilter, IMediaSample *pSample) +static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample) { - AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; + AVIDecImpl* This = (AVIDecImpl *)pin->pin.pinInfo.pFilter; AM_MEDIA_TYPE amt; HRESULT hr; DWORD res; @@ -80,7 +78,6 @@ static HRESULT AVIDec_ProcessSampleData(TransformFilterImpl* pTransformFilter, I DWORD cbSrcStream; LPBYTE pbSrcStream; LONGLONG tStart, tStop; - InputPin *pin = (InputPin *)pTransformFilter->ppPins[0]; EnterCriticalSection(&This->tf.csFilter); if (This->tf.state == State_Stopped) @@ -185,15 +182,13 @@ static HRESULT AVIDec_ProcessEnd(TransformFilterImpl* pTransformFilter) return S_OK; } -static HRESULT AVIDec_ConnectInput(TransformFilterImpl* pTransformFilter, const AM_MEDIA_TYPE * pmt) +static HRESULT AVIDec_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) { - AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; + AVIDecImpl* This = (AVIDecImpl*)pin->pin.pinInfo.pFilter; HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED; TRACE("(%p)->(%p)\n", This, pmt); - AVIDec_Cleanup(pTransformFilter); - /* 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))) @@ -283,15 +278,14 @@ static HRESULT AVIDec_ConnectInput(TransformFilterImpl* pTransformFilter, const } failed: - AVIDec_Cleanup(pTransformFilter); TRACE("Connection refused\n"); return hr; } -static HRESULT AVIDec_Cleanup(TransformFilterImpl* pTransformFilter) +static HRESULT AVIDec_Cleanup(InputPin *pin) { - AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; + AVIDecImpl *This = (AVIDecImpl *)pin->pin.pinInfo.pFilter; TRACE("(%p)->()\n", This); diff --git a/dlls/quartz/avisplit.c b/dlls/quartz/avisplit.c index e712eb9b177..3f1625c63e9 100644 --- a/dlls/quartz/avisplit.c +++ b/dlls/quartz/avisplit.c @@ -183,7 +183,7 @@ static HRESULT AVISplitter_next_request(AVISplitterImpl *This, DWORD streamnumbe /* End of file */ if (stream->index >= stream->entries) { - ERR("END OF STREAM ON %u\n", streamnumber); + TRACE("END OF STREAM ON %u\n", streamnumber); IMediaSample_Release(sample); return S_FALSE; } @@ -213,8 +213,8 @@ static HRESULT AVISplitter_next_request(AVISplitterImpl *This, DWORD streamnumbe /* End of file */ if (stream->index) { + TRACE("END OF STREAM ON %u\n", streamnumber); IMediaSample_Release(sample); - ERR("END OF STREAM ON %u\n", streamnumber); return S_FALSE; } @@ -449,6 +449,8 @@ static HRESULT AVISplitter_first_request(LPVOID iface) have_sample = (hr == S_OK); if (FAILED(hr)) break; + if (hr == S_FALSE) + AVISplitter_SendEndOfFile(This, x); } /* FIXME: Don't do this for each pin that sent an EOF */ @@ -500,6 +502,7 @@ static HRESULT AVISplitter_done_process(LPVOID iface) ResetEvent(stream->packet_queued); } + FIXME("All threads are now terminated\n"); return S_OK; } @@ -514,8 +517,7 @@ static HRESULT AVISplitter_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) static HRESULT AVISplitter_ProcessIndex(AVISplitterImpl *This, AVISTDINDEX **index, LONGLONG qwOffset, DWORD cb) { AVISTDINDEX *pIndex; - int x; - long rest; + int x, rest; *index = NULL; if (cb < sizeof(AVISTDINDEX)) @@ -529,12 +531,7 @@ static HRESULT AVISplitter_ProcessIndex(AVISplitterImpl *This, AVISTDINDEX **ind return E_OUTOFMEMORY; IAsyncReader_SyncRead(((PullPin *)This->Parser.ppPins[0])->pReader, qwOffset, cb, (BYTE *)pIndex); - pIndex = CoTaskMemRealloc(pIndex, pIndex->cb); - if (!pIndex) - return E_OUTOFMEMORY; - - IAsyncReader_SyncRead(((PullPin *)This->Parser.ppPins[0])->pReader, qwOffset, pIndex->cb, (BYTE *)pIndex); - rest = pIndex->cb - sizeof(AVISUPERINDEX) + sizeof(RIFFCHUNK) + sizeof(pIndex->aIndex[0]) * ANYSIZE_ARRAY; + rest = cb - sizeof(AVISUPERINDEX) + sizeof(RIFFCHUNK) + sizeof(pIndex->aIndex); TRACE("FOURCC: %s\n", debugstr_an((char *)&pIndex->fcc, 4)); TRACE("wLongsPerEntry: %hd\n", pIndex->wLongsPerEntry); @@ -550,7 +547,11 @@ static HRESULT AVISplitter_ProcessIndex(AVISplitterImpl *This, AVISTDINDEX **ind || rest < (pIndex->nEntriesInUse * sizeof(DWORD) * pIndex->wLongsPerEntry) || (pIndex->bIndexSubType != AVI_INDEX_SUB_DEFAULT)) { - FIXME("Invalid index chunk encountered\n"); + FIXME("Invalid index chunk encountered: %u/%u, %u/%u, %u/%u, %u/%u\n", + pIndex->bIndexType, AVI_INDEX_OF_CHUNKS, pIndex->wLongsPerEntry, 2, + rest, (pIndex->nEntriesInUse * sizeof(DWORD) * pIndex->wLongsPerEntry), + pIndex->bIndexSubType, AVI_INDEX_SUB_DEFAULT); + *index = NULL; return E_INVALIDARG; } @@ -812,7 +813,7 @@ static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE TRACE("dwSize: %u\n", pIndex->aIndex[x].dwSize); TRACE("dwDuration: %u (unreliable)\n", pIndex->aIndex[x].dwDuration); - AVISplitter_ProcessIndex(This, &stream->stdindex[nstdindex-1], pIndex->aIndex[x].qwOffset, pIndex->aIndex[x].dwSize); + AVISplitter_ProcessIndex(This, &stream->stdindex[x], pIndex->aIndex[x].qwOffset, pIndex->aIndex[x].dwSize); } break; } @@ -976,8 +977,9 @@ static HRESULT AVISplitter_InitializeStreams(AVISplitterImpl *This) frames /= stream->streamheader.dwRate; - TRACE("Duration: %d days, %d hours, %d minutes and %d seconds\n", (DWORD)(frames / 86400), - (DWORD)((frames % 86400) / 3600), (DWORD)((frames % 3600) / 60), (DWORD)(frames % 60)); + TRACE("Duration: %d days, %d hours, %d minutes and %d.%03u seconds\n", (DWORD)(frames / 86400), + (DWORD)((frames % 86400) / 3600), (DWORD)((frames % 3600) / 60), (DWORD)(frames % 60), + (DWORD)(This->Parser.mediaSeeking.llDuration/10000) % 1000); } return S_OK; diff --git a/dlls/quartz/memallocator.c b/dlls/quartz/memallocator.c index 2ee8d71cc8c..1718d197d8c 100644 --- a/dlls/quartz/memallocator.c +++ b/dlls/quartz/memallocator.c @@ -486,7 +486,7 @@ static HRESULT WINAPI StdMediaSample2_GetPointer(IMediaSample2 * iface, BYTE ** { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%p)\n", ppBuffer); + TRACE("(%p)->(%p)\n", iface, ppBuffer); *ppBuffer = This->props.pbBuffer; @@ -513,7 +513,7 @@ static HRESULT WINAPI StdMediaSample2_GetTime(IMediaSample2 * iface, REFERENCE_T HRESULT hr; StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%p, %p)\n", pStart, pEnd); + TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd); if (!(This->props.dwSampleFlags & AM_SAMPLE_TIMEVALID)) hr = VFW_E_SAMPLE_TIME_NOT_SET; @@ -539,7 +539,7 @@ static HRESULT WINAPI StdMediaSample2_SetTime(IMediaSample2 * iface, REFERENCE_T { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%p, %p)\n", pStart, pEnd); + TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd); if (pStart) { @@ -564,7 +564,7 @@ static HRESULT WINAPI StdMediaSample2_IsSyncPoint(IMediaSample2 * iface) { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("()\n"); + TRACE("(%p)->()\n", iface); return (This->props.dwSampleFlags & AM_SAMPLE_SPLICEPOINT) ? S_OK : S_FALSE; } @@ -573,7 +573,7 @@ static HRESULT WINAPI StdMediaSample2_SetSyncPoint(IMediaSample2 * iface, BOOL b { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%s)\n", bIsSyncPoint ? "TRUE" : "FALSE"); + TRACE("(%p)->(%s)\n", iface, bIsSyncPoint ? "TRUE" : "FALSE"); if (bIsSyncPoint) This->props.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT; @@ -587,7 +587,7 @@ static HRESULT WINAPI StdMediaSample2_IsPreroll(IMediaSample2 * iface) { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("()\n"); + TRACE("(%p)->()\n", iface); return (This->props.dwSampleFlags & AM_SAMPLE_PREROLL) ? S_OK : S_FALSE; } @@ -596,7 +596,7 @@ static HRESULT WINAPI StdMediaSample2_SetPreroll(IMediaSample2 * iface, BOOL bIs { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%s)\n", bIsPreroll ? "TRUE" : "FALSE"); + TRACE("(%p)->(%s)\n", iface, bIsPreroll ? "TRUE" : "FALSE"); if (bIsPreroll) This->props.dwSampleFlags |= AM_SAMPLE_PREROLL; @@ -610,7 +610,7 @@ static LONG WINAPI StdMediaSample2_GetActualDataLength(IMediaSample2 * iface) { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("()\n"); + TRACE("(%p)->()\n", iface); return This->props.lActual; } @@ -619,7 +619,7 @@ static HRESULT WINAPI StdMediaSample2_SetActualDataLength(IMediaSample2 * iface, { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%d)\n", len); + TRACE("(%p)->(%d)\n", iface, len); if ((len > This->props.cbBuffer) || (len < 0)) { @@ -637,7 +637,7 @@ static HRESULT WINAPI StdMediaSample2_GetMediaType(IMediaSample2 * iface, AM_MED { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%p)\n", ppMediaType); + TRACE("(%p)->(%p)\n", iface, ppMediaType); if (!This->props.pMediaType) { /* Make sure we return a NULL pointer (required by native Quartz dll) */ @@ -656,7 +656,7 @@ static HRESULT WINAPI StdMediaSample2_SetMediaType(IMediaSample2 * iface, AM_MED { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%p)\n", pMediaType); + TRACE("(%p)->(%p)\n", iface, pMediaType); if (This->props.pMediaType) FreeMediaType(This->props.pMediaType); @@ -670,7 +670,7 @@ static HRESULT WINAPI StdMediaSample2_IsDiscontinuity(IMediaSample2 * iface) { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("()\n"); + TRACE("(%p)->()\n", iface); return (This->props.dwSampleFlags & AM_SAMPLE_DATADISCONTINUITY) ? S_OK : S_FALSE; } @@ -679,7 +679,7 @@ static HRESULT WINAPI StdMediaSample2_SetDiscontinuity(IMediaSample2 * iface, BO { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%s)\n", bIsDiscontinuity ? "TRUE" : "FALSE"); + TRACE("(%p)->(%s)\n", iface, bIsDiscontinuity ? "TRUE" : "FALSE"); if (bIsDiscontinuity) This->props.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY; @@ -693,7 +693,7 @@ static HRESULT WINAPI StdMediaSample2_GetMediaTime(IMediaSample2 * iface, LONGLO { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%p, %p)\n", pStart, pEnd); + TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd); if (This->tMediaStart == INVALID_MEDIA_TIME) return VFW_E_MEDIA_TIME_NOT_SET; @@ -708,7 +708,7 @@ static HRESULT WINAPI StdMediaSample2_SetMediaTime(IMediaSample2 * iface, LONGLO { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%p, %p)\n", pStart, pEnd); + TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd); if (pStart) This->tMediaStart = *pStart; @@ -727,7 +727,7 @@ static HRESULT WINAPI StdMediaSample2_GetProperties(IMediaSample2 * iface, DWORD { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%d, %p)\n", cbProperties, pbProperties); + TRACE("(%p)->(%d, %p)\n", iface, cbProperties, pbProperties); memcpy(pbProperties, &This->props, min(cbProperties, sizeof(This->props))); @@ -738,7 +738,7 @@ static HRESULT WINAPI StdMediaSample2_SetProperties(IMediaSample2 * iface, DWORD { StdMediaSample2 *This = (StdMediaSample2 *)iface; - TRACE("(%d, %p)\n", cbProperties, pbProperties); + TRACE("(%p)->(%d, %p)\n", iface, cbProperties, pbProperties); /* NOTE: pbBuffer and cbBuffer are read-only */ memcpy(&This->props, pbProperties, min(cbProperties, AM_SAMPLE2_PROP_SIZE_WRITABLE)); diff --git a/dlls/quartz/transform.c b/dlls/quartz/transform.c index 322c76aa17f..57e02b8d49d 100644 --- a/dlls/quartz/transform.c +++ b/dlls/quartz/transform.c @@ -50,7 +50,7 @@ static const IPinVtbl TransformFilter_OutputPin_Vtbl; static HRESULT TransformFilter_Input_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) { - TransformFilterImpl* This = (TransformFilterImpl*)iface; + TransformFilterImpl* This = (TransformFilterImpl *)((IPinImpl *)iface)->pinInfo.pFilter; TRACE("%p\n", iface); dump_AM_MEDIA_TYPE(pmt); @@ -65,10 +65,11 @@ static HRESULT TransformFilter_Input_QueryAccept(LPVOID iface, const AM_MEDIA_TY static HRESULT TransformFilter_Output_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) { TransformFilterImpl* pTransformFilter = (TransformFilterImpl*)iface; - AM_MEDIA_TYPE* outpmt = &((OutputPin*)pTransformFilter->ppPins[1])->pin.mtCurrent; + AM_MEDIA_TYPE* outpmt = &pTransformFilter->pmt; TRACE("%p\n", iface); - if (IsEqualIID(&pmt->majortype, &outpmt->majortype) && IsEqualIID(&pmt->subtype, &outpmt->subtype)) + if (IsEqualIID(&pmt->majortype, &outpmt->majortype) + && (IsEqualIID(&pmt->subtype, &outpmt->subtype) || IsEqualIID(&outpmt->subtype, &GUID_NULL))) return S_OK; return S_FALSE; } @@ -165,6 +166,7 @@ HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSI pTransformFilter->pClock = NULL; ZeroMemory(&pTransformFilter->filterInfo, sizeof(FILTER_INFO)); ZeroMemory(&pTransformFilter->pmt, sizeof(pTransformFilter->pmt)); + pTransformFilter->npins = 2; pTransformFilter->ppPins = CoTaskMemAlloc(2 * sizeof(IPin *)); @@ -176,7 +178,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, (SAMPLEPROC_PUSH)pFuncsTable->pfnProcessSampleData, pTransformFilter, TransformFilter_Input_QueryAccept, NULL, &pTransformFilter->csFilter, NULL, &pTransformFilter->ppPins[0]); + hr = InputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, (SAMPLEPROC_PUSH)pFuncsTable->pfnProcessSampleData, NULL, TransformFilter_Input_QueryAccept, NULL, &pTransformFilter->csFilter, NULL, &pTransformFilter->ppPins[0]); if (SUCCEEDED(hr)) { @@ -186,6 +188,8 @@ HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSI props.cbBuffer = 0; /* Will be updated at connection time */ props.cBuffers = 1; + ((InputPin *)pTransformFilter->ppPins[0])->pin.pUserData = pTransformFilter->ppPins[0]; + hr = OutputPin_Construct(&TransformFilter_OutputPin_Vtbl, sizeof(OutputPin), &piOutput, &props, pTransformFilter, TransformFilter_Output_QueryAccept, &pTransformFilter->csFilter, &pTransformFilter->ppPins[1]); if (FAILED(hr)) @@ -268,7 +272,7 @@ static ULONG WINAPI TransformFilter_Release(IBaseFilter * iface) if (This->pClock) IReferenceClock_Release(This->pClock); - for (i = 0; i < 2; i++) + for (i = 0; i < This->npins; i++) { IPin *pConnectedTo; @@ -316,6 +320,7 @@ static HRESULT WINAPI TransformFilter_GetClassID(IBaseFilter * iface, CLSID * pC static HRESULT WINAPI TransformFilter_Stop(IBaseFilter * iface) { TransformFilterImpl *This = (TransformFilterImpl *)iface; + HRESULT hr = S_OK; TRACE("(%p/%p)\n", This, iface); @@ -323,29 +328,33 @@ static HRESULT WINAPI TransformFilter_Stop(IBaseFilter * iface) { This->state = State_Stopped; if (This->pFuncsTable->pfnProcessEnd) - This->pFuncsTable->pfnProcessEnd(This); + hr = This->pFuncsTable->pfnProcessEnd(This); } LeaveCriticalSection(&This->csFilter); - return S_OK; + return hr; } static HRESULT WINAPI TransformFilter_Pause(IBaseFilter * iface) { TransformFilterImpl *This = (TransformFilterImpl *)iface; + HRESULT hr; TRACE("(%p/%p)->()\n", This, iface); EnterCriticalSection(&This->csFilter); { if (This->state == State_Stopped) - IBaseFilter_Run(iface, -1); + hr = IBaseFilter_Run(iface, -1); + else + hr = S_OK; - This->state = State_Paused; + if (SUCCEEDED(hr)) + This->state = State_Paused; } LeaveCriticalSection(&This->csFilter); - return S_OK; + return hr; } static HRESULT WINAPI TransformFilter_Run(IBaseFilter * iface, REFERENCE_TIME tStart) @@ -361,12 +370,16 @@ static HRESULT WINAPI TransformFilter_Run(IBaseFilter * iface, REFERENCE_TIME tS { ((InputPin *)This->ppPins[0])->end_of_stream = 0; if (This->pFuncsTable->pfnProcessBegin) - This->pFuncsTable->pfnProcessBegin(This); - OutputPin_CommitAllocator((OutputPin *)This->ppPins[1]); + hr = This->pFuncsTable->pfnProcessBegin(This); + if (SUCCEEDED(hr)) + hr = OutputPin_CommitAllocator((OutputPin *)This->ppPins[1]); } - This->rtStreamStart = tStart; - This->state = State_Running; + if (SUCCEEDED(hr)) + { + This->rtStreamStart = tStart; + This->state = State_Running; + } } LeaveCriticalSection(&This->csFilter); @@ -433,7 +446,7 @@ static HRESULT TransformFilter_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, /* Our pins are static, not changing so setting static tick count is ok */ *lastsynctick = 0; - if (pos >= 2) + if (pos >= This->npins) return S_FALSE; *pin = This->ppPins[pos]; @@ -556,12 +569,12 @@ static HRESULT WINAPI TransformFilter_InputPin_ReceiveConnection(IPin * iface, I pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter; - hr = pTransform->pFuncsTable->pfnConnectInput(pTransform, pmt); + hr = pTransform->pFuncsTable->pfnConnectInput(This, pmt); if (SUCCEEDED(hr)) { hr = InputPin_ReceiveConnection(iface, pReceivePin, pmt); if (FAILED(hr)) - pTransform->pFuncsTable->pfnCleanup(pTransform); + pTransform->pFuncsTable->pfnCleanup(This); } return hr; @@ -575,7 +588,7 @@ static HRESULT WINAPI TransformFilter_InputPin_Disconnect(IPin * iface) TRACE("(%p)->()\n", iface); pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter; - pTransform->pFuncsTable->pfnCleanup(pTransform); + pTransform->pFuncsTable->pfnCleanup(This); return IPinImpl_Disconnect(iface); } diff --git a/dlls/quartz/transform.h b/dlls/quartz/transform.h index 0f20b6ed026..f39ff47846b 100644 --- a/dlls/quartz/transform.h +++ b/dlls/quartz/transform.h @@ -23,12 +23,12 @@ typedef struct TransformFilterImpl TransformFilterImpl; typedef struct TransformFuncsTable { - HRESULT (*pfnProcessBegin) (TransformFilterImpl* This); - HRESULT (*pfnProcessSampleData) (TransformFilterImpl* This, IMediaSample *pSample); - HRESULT (*pfnProcessEnd) (TransformFilterImpl* This); - HRESULT (*pfnQueryConnect) (TransformFilterImpl* This, const AM_MEDIA_TYPE * pmt); - HRESULT (*pfnConnectInput) (TransformFilterImpl* This, const AM_MEDIA_TYPE * pmt); - HRESULT (*pfnCleanup) (TransformFilterImpl* This); + HRESULT (*pfnProcessBegin) (TransformFilterImpl *This); + HRESULT (*pfnProcessSampleData) (InputPin *pin, IMediaSample *pSample); + HRESULT (*pfnProcessEnd) (TransformFilterImpl *This); + HRESULT (*pfnQueryConnect) (TransformFilterImpl *This, const AM_MEDIA_TYPE * pmt); + HRESULT (*pfnConnectInput) (InputPin *pin, const AM_MEDIA_TYPE * pmt); + HRESULT (*pfnCleanup) (InputPin *pin); } TransformFuncsTable; struct TransformFilterImpl @@ -44,7 +44,8 @@ struct TransformFilterImpl CLSID clsid; struct MediaSeekingImpl mediaSeeking; - IPin ** ppPins; + IPin **ppPins; + ULONG npins; AM_MEDIA_TYPE pmt; const TransformFuncsTable * pFuncsTable; diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c index 629ad1debf9..c7d65825cab 100644 --- a/dlls/quartz/videorenderer.c +++ b/dlls/quartz/videorenderer.c @@ -37,7 +37,7 @@ #include "ddraw.h" #include "dvdmedia.h" -#include "assert.h" +#include #include "wine/unicode.h" #include "wine/debug.h" diff --git a/dlls/rasapi32/rasapi.c b/dlls/rasapi32/rasapi.c index f14694aefe2..704a8bcfe1e 100644 --- a/dlls/rasapi32/rasapi.c +++ b/dlls/rasapi32/rasapi.c @@ -23,6 +23,7 @@ #include "windef.h" #include "winbase.h" #include "ras.h" +#include "raserror.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ras); diff --git a/dlls/rasapi32/tests/rasapi.c b/dlls/rasapi32/tests/rasapi.c index 4130392b3e8..da733a134da 100644 --- a/dlls/rasapi32/tests/rasapi.c +++ b/dlls/rasapi32/tests/rasapi.c @@ -24,6 +24,7 @@ #include #include #include "ras.h" +#include "raserror.h" static HMODULE hmodule; static DWORD (WINAPI *pRasEnumDevicesA)(LPRASDEVINFOA, LPDWORD, LPDWORD); @@ -54,7 +55,11 @@ static void test_rasenum(void) /* create the return buffer */ result = pRasEnumDevicesA(NULL, &bufsize, &cDevices); - trace("RasEnumDevicesA: buffersize %d\n", cb); + if(ERROR_RASMAN_CANNOT_INITIALIZE == result) { + win_skip("RAS configuration problem\n"); + return; + } + trace("RasEnumDevicesA: returned %d buffersize %d\n", result, cb); ok(result == ERROR_BUFFER_TOO_SMALL, "Expected ERROR_BUFFER_TOO_SMALL, got %08d\n", result); diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index a801ee2ecc6..db9728c3c10 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -140,10 +140,10 @@ + WM_SETTEXT (resets undo stack !) (proper style?) ANSI&Unicode - WM_STYLECHANGING - WM_STYLECHANGED (things like read-only flag) - - WM_UNICHAR - + + WM_UNICHAR + Notifications - + * EN_CHANGE (sent from the wrong place) - EN_CORRECTTEXT - EN_DROPFILES @@ -1814,6 +1814,8 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd) { ed->vert_si.nPage = 0; ed->vert_si.nPos = 0; + OleInitialize(NULL); + return ed; } @@ -1882,6 +1884,7 @@ void ME_DestroyEditor(ME_TextEditor *editor) DeleteObject(editor->hbrBackground); if(editor->lpOleCallback) IUnknown_Release(editor->lpOleCallback); + OleUninitialize(); FREE_OBJ(editor->pBuffer); FREE_OBJ(editor->pCursors); @@ -2101,10 +2104,9 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, UNSUPPORTED_MSG(EM_SETWORDBREAKPROCEX) UNSUPPORTED_MSG(WM_STYLECHANGING) UNSUPPORTED_MSG(WM_STYLECHANGED) -/* UNSUPPORTED_MSG(WM_UNICHAR) FIXME missing in Wine headers */ - + /* Messages specific to Richedit controls */ - + case EM_STREAMIN: return ME_StreamIn(editor, wParam, (EDITSTREAM*)lParam, TRUE); case EM_STREAMOUT: @@ -2308,7 +2310,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, style = ME_GetSelectionInsertStyle(editor); ME_InternalDeleteText(editor, from, to - from); if (pStruct->codepage != 1200 && lParam && !strncmp((char *)lParam, "{\\rtf", 5)) - ME_StreamInRTFString(editor, 0, (char *)lParam); + ME_StreamInRTFString(editor, 1, (char *)lParam); else ME_InsertTextFromCursor(editor, 0, wszText, len, style); ME_ReleaseStyle(style); @@ -3263,6 +3265,23 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, } return 0; } + case WM_UNICHAR: + if (unicode) + { + if(wParam == UNICODE_NOCHAR) return TRUE; + if(wParam <= 0x000fffff) + { + if(wParam > 0xffff) /* convert to surrogates */ + { + wParam -= 0x10000; + SendMessageW(editor->hWnd, WM_CHAR, (wParam >> 10) + 0xd800, 0); + SendMessageW(editor->hWnd, WM_CHAR, (wParam & 0x03ff) + 0xdc00, 0); + } + else SendMessageW(editor->hWnd, WM_CHAR, wParam, 0); + } + return 0; + } + break; case EM_STOPGROUPTYPING: ME_CommitUndo(editor); /* End coalesced undos for typed characters */ return 0; diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index e6bc67f92d5..15cef753388 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -3180,6 +3180,12 @@ static void test_EM_SETTEXTEX(void) WCHAR TestItem1[] = {'T', 'e', 's', 't', 'S', 'o', 'm', 'e', 'T', 'e', 'x', 't', 0}; + WCHAR TestItem1alt[] = {'T', 'T', 'e', 's', + 't', 'S', 'o', 'm', + 'e', 'T', 'e', 'x', + 't', 't', 'S', 'o', + 'm', 'e', 'T', 'e', + 'x', 't', 0}; WCHAR TestItem2[] = {'T', 'e', 's', 't', 'S', 'o', 'm', 'e', 'T', 'e', 'x', 't', @@ -3208,6 +3214,7 @@ static void test_EM_SETTEXTEX(void) ' ','\r', 0}; #define MAX_BUF_LEN 1024 WCHAR buf[MAX_BUF_LEN]; + char bufACP[MAX_BUF_LEN]; char * p; int result; CHARRANGE cr; @@ -3227,7 +3234,7 @@ static void test_EM_SETTEXTEX(void) "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n"); /* Unlike WM_SETTEXT/WM_GETTEXT pair, EM_SETTEXTEX/EM_GETTEXTEX does not - convert \r to \r\n on return + convert \r to \r\n on return: !ST_SELECTION && Unicode && !\rtf */ setText.codepage = 1200; /* no constant for unicode */ getText.codepage = 1200; /* no constant for unicode */ @@ -3273,7 +3280,7 @@ static void test_EM_SETTEXTEX(void) "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n"); - /* \r\n pairs get changed into \r */ + /* \r\n pairs get changed into \r: !ST_SELECTION && Unicode && !\rtf */ setText.codepage = 1200; /* no constant for unicode */ getText.codepage = 1200; /* no constant for unicode */ getText.cb = MAX_BUF_LEN; @@ -3286,7 +3293,7 @@ static void test_EM_SETTEXTEX(void) ok(lstrcmpW(buf, TestItem3_after) == 0, "EM_SETTEXTEX did not convert properly\n"); - /* \n also gets changed to \r */ + /* \n also gets changed to \r: !ST_SELECTION && Unicode && !\rtf */ setText.codepage = 1200; /* no constant for unicode */ getText.codepage = 1200; /* no constant for unicode */ getText.cb = MAX_BUF_LEN; @@ -3299,7 +3306,7 @@ static void test_EM_SETTEXTEX(void) ok(lstrcmpW(buf, TestItem3_after) == 0, "EM_SETTEXTEX did not convert properly\n"); - /* \r\r\n gets changed into single space */ + /* \r\r\n gets changed into single space: !ST_SELECTION && Unicode && !\rtf */ setText.codepage = 1200; /* no constant for unicode */ getText.codepage = 1200; /* no constant for unicode */ getText.cb = MAX_BUF_LEN; @@ -3312,6 +3319,7 @@ static void test_EM_SETTEXTEX(void) ok(lstrcmpW(buf, TestItem4_after) == 0, "EM_SETTEXTEX did not convert properly\n"); + /* !ST_SELECTION && Unicode && !\rtf */ result = SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) NULL); SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf); @@ -3321,14 +3329,14 @@ static void test_EM_SETTEXTEX(void) ok(lstrlenW(buf) == 0, "EM_SETTEXTEX with NULL lParam should clear rich edit.\n"); - /* put some text back */ + /* put some text back: !ST_SELECTION && Unicode && !\rtf */ setText.flags = 0; SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem1); /* select some text */ cr.cpMax = 1; cr.cpMin = 3; SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); - /* replace current selection */ + /* replace current selection: ST_SELECTION && Unicode && !\rtf */ setText.flags = ST_SELECTION; result = SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) NULL); @@ -3337,14 +3345,14 @@ static void test_EM_SETTEXTEX(void) " with no text should return 0. Got %i\n", result); - /* put some text back */ + /* put some text back: !ST_SELECTION && Unicode && !\rtf */ setText.flags = 0; SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem1); /* select some text */ cr.cpMax = 1; cr.cpMin = 3; SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); - /* replace current selection */ + /* replace current selection: ST_SELECTION && Unicode && !\rtf */ setText.flags = ST_SELECTION; result = SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem1); @@ -3369,6 +3377,7 @@ static void test_EM_SETTEXTEX(void) (WPARAM)(SF_RTF), (LPARAM)&es); trace("EM_STREAMOUT produced: \n%s\n", (char *)buf); + /* !ST_SELECTION && !Unicode && \rtf */ setText.codepage = CP_ACP;/* EM_STREAMOUT saved as ANSI string */ getText.codepage = 1200; /* no constant for unicode */ getText.cb = MAX_BUF_LEN; @@ -3382,6 +3391,66 @@ static void test_EM_SETTEXTEX(void) ok(lstrcmpW(buf, TestItem1) == 0, "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n"); + /* The following test demonstrates that EM_SETTEXTEX supports RTF strings with a selection */ + SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "TestSomeText"); /* TestItem1 */ + p = (char *)buf; + es.dwCookie = (DWORD_PTR)&p; + es.dwError = 0; + es.pfnCallback = test_WM_SETTEXT_esCallback; + memset(buf, 0, sizeof(buf)); + SendMessage(hwndRichEdit, EM_STREAMOUT, + (WPARAM)(SF_RTF), (LPARAM)&es); + trace("EM_STREAMOUT produced: \n%s\n", (char *)buf); + + /* select some text */ + cr.cpMax = 1; + cr.cpMin = 3; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + + /* ST_SELECTION && !Unicode && \rtf */ + setText.codepage = CP_ACP;/* EM_STREAMOUT saved as ANSI string */ + getText.codepage = 1200; /* no constant for unicode */ + getText.cb = MAX_BUF_LEN; + getText.flags = GT_DEFAULT; + getText.lpDefaultChar = NULL; + getText.lpUsedDefChar = NULL; + + setText.flags = ST_SELECTION; + SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) buf); + SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf); + ok(lstrcmpW(buf, TestItem1alt) == 0, + "EM_GETTEXTEX results not what was set by EM_SETTEXTEX when" + " using ST_SELECTION on an RTF string and non-Unicode\n"); + + /* The following test demonstrates that EM_SETTEXTEX replacing a selection */ + setText.codepage = 1200; /* no constant for unicode */ + getText.codepage = CP_ACP; + getText.cb = MAX_BUF_LEN; + + setText.flags = 0; + SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem1); /* TestItem1 */ + SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) bufACP); + + /* select some text */ + cr.cpMax = 1; + cr.cpMin = 3; + SendMessage(hwndRichEdit, EM_EXSETSEL, 0, (LPARAM) &cr); + + /* ST_SELECTION && !Unicode && !\rtf */ + setText.codepage = CP_ACP; + getText.codepage = 1200; /* no constant for unicode */ + getText.cb = MAX_BUF_LEN; + getText.flags = GT_DEFAULT; + getText.lpDefaultChar = NULL; + getText.lpUsedDefChar = NULL; + + setText.flags = ST_SELECTION; + SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) bufACP); + SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf); + ok(lstrcmpW(buf, TestItem1alt) == 0, + "EM_GETTEXTEX results not what was set by EM_SETTEXTEX when" + " using ST_SELECTION and non-Unicode\n"); + DestroyWindow(hwndRichEdit); } diff --git a/dlls/rpcrt4/rpc_binding.c b/dlls/rpcrt4/rpc_binding.c index e42b8f9d676..a439bc371de 100644 --- a/dlls/rpcrt4/rpc_binding.c +++ b/dlls/rpcrt4/rpc_binding.c @@ -481,7 +481,18 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU next = strchr(data, '@'); if (next) { - if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data); + UUID uuid; + RPC_STATUS status; + RPC_CSTR str_uuid = (unsigned char*)RPCRT4_strndupA(data, next - data); + status = UuidFromStringA(str_uuid, &uuid); + if (status != RPC_S_OK) { + HeapFree(GetProcessHeap(), 0, str_uuid); + return status; + } + if (ObjUuid) + *ObjUuid = str_uuid; + else + HeapFree(GetProcessHeap(), 0, str_uuid); data = next+1; } @@ -579,7 +590,18 @@ RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjU next = strchrW(data, '@'); if (next) { - if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data); + UUID uuid; + RPC_STATUS status; + RPC_WSTR str_uuid = RPCRT4_strndupW(data, next - data); + status = UuidFromStringW(str_uuid, &uuid); + if (status != RPC_S_OK) { + HeapFree(GetProcessHeap(), 0, str_uuid); + return status; + } + if (ObjUuid) + *ObjUuid = str_uuid; + else + HeapFree(GetProcessHeap(), 0, str_uuid); data = next+1; } diff --git a/dlls/rpcrt4/rpc_epmap.c b/dlls/rpcrt4/rpc_epmap.c index 074217e72c9..19c11f880ca 100644 --- a/dlls/rpcrt4/rpc_epmap.c +++ b/dlls/rpcrt4/rpc_epmap.c @@ -447,6 +447,9 @@ RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE 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) diff --git a/dlls/rpcrt4/tests/rpc.c b/dlls/rpcrt4/tests/rpc.c index 671159d9107..19a0a944743 100644 --- a/dlls/rpcrt4/tests/rpc.c +++ b/dlls/rpcrt4/tests/rpc.c @@ -611,9 +611,7 @@ static void test_RpcStringBindingParseA(void) /* test with invalid uuid */ status = RpcStringBindingParseA(invalid_uuid_binding, NULL, &protseq, NULL, NULL, NULL); - todo_wine ok(status == RPC_S_INVALID_STRING_UUID, "RpcStringBindingParseA should have returned RPC_S_INVALID_STRING_UUID instead of %ld\n", status); - todo_wine ok(protseq == NULL, "protseq was %p instead of NULL\n", protseq); /* test with invalid endpoint */ diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c index f957a1ffa7c..e681d69f7dd 100644 --- a/dlls/rsaenh/rsaenh.c +++ b/dlls/rsaenh/rsaenh.c @@ -2826,10 +2826,10 @@ BOOL WINAPI RSAENH_CPSetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam { CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pbData; - /* salt length can't be greater than 128 bits = 16 bytes */ - if (blob->cbData > 16) + /* salt length can't be greater than 184 bits = 24 bytes */ + if (blob->cbData > 24) { - SetLastError(ERROR_INVALID_PARAMETER); + SetLastError(NTE_BAD_DATA); return FALSE; } memcpy(pCryptKey->abKeyValue + pCryptKey->dwKeyLen, blob->pbData, diff --git a/dlls/rsaenh/tests/rsaenh.c b/dlls/rsaenh/tests/rsaenh.c index 479b4286d46..4f25831f217 100644 --- a/dlls/rsaenh/tests/rsaenh.c +++ b/dlls/rsaenh/tests/rsaenh.c @@ -749,6 +749,8 @@ static void test_rc2(void) if (!result) { ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError()); } else { + CRYPT_INTEGER_BLOB salt; + result = CryptHashData(hHash, (BYTE*)pbData, sizeof(pbData), 0); ok(result, "%08x\n", GetLastError()); @@ -812,6 +814,19 @@ static void test_rc2(void) result = CryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwDataLen); ok(result, "%08x\n", GetLastError()); + /* What sizes salt can I set? */ + salt.pbData = pbData; + for (i=0; i<24; i++) + { + salt.cbData = i; + result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0); + ok(result, "setting salt failed for size %d: %08x\n", i, GetLastError()); + } + salt.cbData = 25; + SetLastError(0xdeadbeef); + result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0); + ok(!result && GetLastError() == NTE_BAD_DATA, "%08x\n", GetLastError()); + result = CryptDestroyKey(hKey); ok(result, "%08x\n", GetLastError()); } @@ -901,6 +916,8 @@ static void test_rc4(void) /* rsaenh compiled without OpenSSL */ ok(GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError()); } else { + CRYPT_INTEGER_BLOB salt; + result = CryptHashData(hHash, (BYTE*)pbData, sizeof(pbData), 0); ok(result, "%08x\n", GetLastError()); @@ -949,6 +966,19 @@ static void test_rc4(void) result = CryptDecrypt(hKey, (HCRYPTHASH)NULL, TRUE, 0, pbData, &dwDataLen); ok(result, "%08x\n", GetLastError()); + /* What sizes salt can I set? */ + salt.pbData = pbData; + for (i=0; i<24; i++) + { + salt.cbData = i; + result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0); + ok(result, "setting salt failed for size %d: %08x\n", i, GetLastError()); + } + salt.cbData = 25; + SetLastError(0xdeadbeef); + result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0); + ok(!result && GetLastError() == NTE_BAD_DATA, "%08x\n", GetLastError()); + result = CryptDestroyKey(hKey); ok(result, "%08x\n", GetLastError()); } diff --git a/dlls/secur32/tests/ntlm.c b/dlls/secur32/tests/ntlm.c index b1f6c3fe006..4667ef0a2c6 100644 --- a/dlls/secur32/tests/ntlm.c +++ b/dlls/secur32/tests/ntlm.c @@ -927,6 +927,8 @@ static void testSignSeal(void) workgroup[] = "WORKGROUP", test_pass[] = "testpass"; + complex_data[1].pvBuffer = complex_data[3].pvBuffer = NULL; + /**************************************************************** * This is basically the same as in testAuth with a fake server, * as we need a valid, authenticated context. diff --git a/dlls/secur32/tests/schannel.c b/dlls/secur32/tests/schannel.c index b4eaf124193..904b6fd6882 100644 --- a/dlls/secur32/tests/schannel.c +++ b/dlls/secur32/tests/schannel.c @@ -245,7 +245,7 @@ static void testAcquireSecurityContext(void) pFreeCredentialsHandle(&cred); /* but fails for inbound. */ st = pAcquireCredentialsHandleA(NULL, unisp_name_a, SECPKG_CRED_INBOUND, - NULL, &schanCred, NULL, NULL, NULL, NULL); + NULL, &schanCred, NULL, NULL, &cred, NULL); ok(st == SEC_E_NO_CREDENTIALS, "Expected SEC_E_NO_CREDENTIALS, got %08x\n", st); diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c index 5eb76f7ffb0..a026e8babe0 100644 --- a/dlls/shell32/autocomplete.c +++ b/dlls/shell32/autocomplete.c @@ -61,8 +61,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell); typedef struct { - const IAutoCompleteVtbl *lpVtbl; - const IAutoComplete2Vtbl *lpvtblAutoComplete2; + const IAutoComplete2Vtbl *lpVtbl; LONG ref; BOOL enabled; HWND hwndEdit; @@ -75,20 +74,14 @@ typedef struct AUTOCOMPLETEOPTIONS options; } IAutoCompleteImpl; -static const IAutoCompleteVtbl acvt; -static const IAutoComplete2Vtbl ac2vt; - -static inline IAutoCompleteImpl *impl_from_IAutoComplete2( IAutoComplete2 *iface ) -{ - return (IAutoCompleteImpl *)((char*)iface - FIELD_OFFSET(IAutoCompleteImpl, lpvtblAutoComplete2)); -} +static const IAutoComplete2Vtbl acvt; /* converts This to an interface pointer */ #define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) -#define _IAutoComplete2_(This) (IAutoComplete2*)&(This->lpvtblAutoComplete2) +#define _IAutoComplete2_(This) (IAutoComplete2*)&(This->lpvtbl) static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT APIENTRY ACLBoxSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -109,7 +102,6 @@ HRESULT WINAPI IAutoComplete_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVO lpac->ref = 1; lpac->lpVtbl = &acvt; - lpac->lpvtblAutoComplete2 = &ac2vt; lpac->enabled = TRUE; lpac->enumstr = NULL; lpac->options = ACO_AUTOAPPEND; @@ -131,8 +123,8 @@ HRESULT WINAPI IAutoComplete_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVO /************************************************************************** * AutoComplete_QueryInterface */ -static HRESULT WINAPI IAutoComplete_fnQueryInterface( - IAutoComplete * iface, +static HRESULT WINAPI IAutoComplete2_fnQueryInterface( + IAutoComplete2 * iface, REFIID riid, LPVOID *ppvObj) { @@ -141,22 +133,16 @@ static HRESULT WINAPI IAutoComplete_fnQueryInterface( TRACE("(%p)->(\n\tIID:\t%s,%p)\n", This, shdebugstr_guid(riid), ppvObj); *ppvObj = NULL; - if(IsEqualIID(riid, &IID_IUnknown)) - { - *ppvObj = This; - } - else if(IsEqualIID(riid, &IID_IAutoComplete)) + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IAutoComplete) || + IsEqualIID(riid, &IID_IAutoComplete2)) { - *ppvObj = (IAutoComplete*)This; - } - else if(IsEqualIID(riid, &IID_IAutoComplete2)) - { - *ppvObj = _IAutoComplete2_ (This); + *ppvObj = (IAutoComplete2*)This; } if (*ppvObj) { - IAutoComplete_AddRef((IAutoComplete*)*ppvObj); + IUnknown_AddRef((IUnknown*)*ppvObj); TRACE("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj); return S_OK; } @@ -165,10 +151,10 @@ static HRESULT WINAPI IAutoComplete_fnQueryInterface( } /****************************************************************************** - * IAutoComplete_fnAddRef + * IAutoComplete2_fnAddRef */ -static ULONG WINAPI IAutoComplete_fnAddRef( - IAutoComplete * iface) +static ULONG WINAPI IAutoComplete2_fnAddRef( + IAutoComplete2 * iface) { IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; ULONG refCount = InterlockedIncrement(&This->ref); @@ -179,10 +165,10 @@ static ULONG WINAPI IAutoComplete_fnAddRef( } /****************************************************************************** - * IAutoComplete_fnRelease + * IAutoComplete2_fnRelease */ -static ULONG WINAPI IAutoComplete_fnRelease( - IAutoComplete * iface) +static ULONG WINAPI IAutoComplete2_fnRelease( + IAutoComplete2 * iface) { IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; ULONG refCount = InterlockedDecrement(&This->ref); @@ -203,10 +189,10 @@ static ULONG WINAPI IAutoComplete_fnRelease( } /****************************************************************************** - * IAutoComplete_fnEnable + * IAutoComplete2_fnEnable */ -static HRESULT WINAPI IAutoComplete_fnEnable( - IAutoComplete * iface, +static HRESULT WINAPI IAutoComplete2_fnEnable( + IAutoComplete2 * iface, BOOL fEnable) { IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; @@ -221,10 +207,10 @@ static HRESULT WINAPI IAutoComplete_fnEnable( } /****************************************************************************** - * IAutoComplete_fnInit + * IAutoComplete2_fnInit */ -static HRESULT WINAPI IAutoComplete_fnInit( - IAutoComplete * iface, +static HRESULT WINAPI IAutoComplete2_fnInit( + IAutoComplete2 * iface, HWND hwndEdit, IUnknown *punkACL, LPCOLESTR pwzsRegKeyPath, @@ -312,91 +298,7 @@ static HRESULT WINAPI IAutoComplete_fnInit( } /************************************************************************** - * IAutoComplete_fnVTable - */ -static const IAutoCompleteVtbl acvt = -{ - IAutoComplete_fnQueryInterface, - IAutoComplete_fnAddRef, - IAutoComplete_fnRelease, - IAutoComplete_fnInit, - IAutoComplete_fnEnable, -}; - -/************************************************************************** - * AutoComplete2_QueryInterface - */ -static HRESULT WINAPI IAutoComplete2_fnQueryInterface( - IAutoComplete2 * iface, - REFIID riid, - LPVOID *ppvObj) -{ - IAutoCompleteImpl *This = impl_from_IAutoComplete2(iface); - - TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj); - - return IAutoComplete_QueryInterface((IAutoComplete*)This, riid, ppvObj); -} - -/****************************************************************************** - * IAutoComplete2_fnAddRef - */ -static ULONG WINAPI IAutoComplete2_fnAddRef( - IAutoComplete2 * iface) -{ - IAutoCompleteImpl *This = impl_from_IAutoComplete2(iface); - - TRACE ("(%p)->(count=%u)\n", This, This->ref); - - return IAutoComplete2_AddRef((IAutoComplete*)This); -} - -/****************************************************************************** - * IAutoComplete2_fnRelease - */ -static ULONG WINAPI IAutoComplete2_fnRelease( - IAutoComplete2 * iface) -{ - IAutoCompleteImpl *This = impl_from_IAutoComplete2(iface); - - TRACE ("(%p)->(count=%u)\n", This, This->ref); - - return IAutoComplete_Release((IAutoComplete*)This); -} - -/****************************************************************************** - * IAutoComplete2_fnEnable - */ -static HRESULT WINAPI IAutoComplete2_fnEnable( - IAutoComplete2 * iface, - BOOL fEnable) -{ - IAutoCompleteImpl *This = impl_from_IAutoComplete2(iface); - - TRACE ("(%p)->(%s)\n", This, (fEnable)?"true":"false"); - - return IAutoComplete_Enable((IAutoComplete*)This, fEnable); -} - -/****************************************************************************** - * IAutoComplete2_fnInit - */ -static HRESULT WINAPI IAutoComplete2_fnInit( - IAutoComplete2 * iface, - HWND hwndEdit, - IUnknown *punkACL, - LPCOLESTR pwzsRegKeyPath, - LPCOLESTR pwszQuickComplete) -{ - IAutoCompleteImpl *This = impl_from_IAutoComplete2(iface); - - TRACE("(%p)\n", This); - - return IAutoComplete_Init((IAutoComplete*)This, hwndEdit, punkACL, pwzsRegKeyPath, pwszQuickComplete); -} - -/************************************************************************** - * IAutoComplete_fnGetOptions + * IAutoComplete2_fnGetOptions */ static HRESULT WINAPI IAutoComplete2_fnGetOptions( IAutoComplete2 * iface, @@ -404,7 +306,7 @@ static HRESULT WINAPI IAutoComplete2_fnGetOptions( { HRESULT hr = S_OK; - IAutoCompleteImpl *This = impl_from_IAutoComplete2(iface); + IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; TRACE("(%p) -> (%p)\n", This, pdwFlag); @@ -414,7 +316,7 @@ static HRESULT WINAPI IAutoComplete2_fnGetOptions( } /************************************************************************** - * IAutoComplete_fnSetOptions + * IAutoComplete2_fnSetOptions */ static HRESULT WINAPI IAutoComplete2_fnSetOptions( IAutoComplete2 * iface, @@ -422,7 +324,7 @@ static HRESULT WINAPI IAutoComplete2_fnSetOptions( { HRESULT hr = S_OK; - IAutoCompleteImpl *This = impl_from_IAutoComplete2(iface); + IAutoCompleteImpl *This = (IAutoCompleteImpl *)iface; TRACE("(%p) -> (0x%x)\n", This, dwFlag); @@ -434,7 +336,7 @@ static HRESULT WINAPI IAutoComplete2_fnSetOptions( /************************************************************************** * IAutoComplete2_fnVTable */ -static const IAutoComplete2Vtbl ac2vt = +static const IAutoComplete2Vtbl acvt = { IAutoComplete2_fnQueryInterface, IAutoComplete2_fnAddRef, diff --git a/dlls/shell32/control.c b/dlls/shell32/control.c index 642e6114320..aa5abfe5b9c 100644 --- a/dlls/shell32/control.c +++ b/dlls/shell32/control.c @@ -237,6 +237,7 @@ static void Control_WndProc_Create(HWND hWnd, const CREATESTRUCTW* cs) LVITEMW lvItem; INITCOMMONCONTROLSEX icex; INT sb_parts; + int itemidx; SetWindowLongPtrW(hWnd, 0, (LONG_PTR)panel); panel->hWnd = hWnd; @@ -296,10 +297,10 @@ static void Control_WndProc_Create(HWND hWnd, const CREATESTRUCTW* cs) lvItem.iImage = index; lvItem.lParam = (LPARAM) item; - ListView_InsertItemW(panel->hWndListView, &lvItem); + itemidx = ListView_InsertItemW(panel->hWndListView, &lvItem); /* add the description */ - ListView_SetItemTextW(panel->hWndListView, menucount, 1, + ListView_SetItemTextW(panel->hWndListView, itemidx, 1, applet->info[i].szInfo); /* update menu bar, increment count */ @@ -510,6 +511,8 @@ static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg, if (item) SetWindowTextW(panel->hWndStatusBar, item->applet->info[item->id].szInfo); + else + SetWindowTextW(panel->hWndStatusBar, NULL); return 0; } @@ -532,6 +535,18 @@ static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg, if (item) SetWindowTextW(panel->hWndStatusBar, item->applet->info[item->id].szInfo); } + else if ((HIWORD(lParam1) == 0xFFFF) && (lParam2 == 0)) + { + /* reset status bar description to that of the selected icon */ + CPlItem *item = Control_GetCPlItem_From_ListView(panel); + + if (item) + SetWindowTextW(panel->hWndStatusBar, item->applet->info[item->id].szInfo); + else + SetWindowTextW(panel->hWndStatusBar, NULL); + + return 0; + } else SetWindowTextW(panel->hWndStatusBar, NULL); diff --git a/dlls/shell32/shell32_Ko.rc b/dlls/shell32/shell32_Ko.rc index de3cf61b0ab..c688c0c6a12 100644 --- a/dlls/shell32/shell32_Ko.rc +++ b/dlls/shell32/shell32_Ko.rc @@ -93,13 +93,13 @@ END MENU_CPANEL MENU BEGIN - POPUP "&File" + POPUP "ÆÄÀÏ(&F)" BEGIN MENUITEM SEPARATOR - MENUITEM "E&xit", IDM_CPANEL_EXIT + MENUITEM "³ª±â±â(&X)", IDM_CPANEL_EXIT END - POPUP "&View" + POPUP "º¸±â(&V)" BEGIN MENUITEM "Å« ¾ÆÀÌÄÜ(&G)", FCIDM_SHVIEW_BIGICON MENUITEM "ÀÛÀº ¾ÆÀÌÄÜ(&M)", FCIDM_SHVIEW_SMALLICON @@ -107,9 +107,9 @@ BEGIN MENUITEM "ÀÚ¼¼È÷(&D)", FCIDM_SHVIEW_REPORTVIEW END - POPUP "&Help" + POPUP "µµ¿ò¸»(&H)" BEGIN - MENUITEM "&About Control Panel...", IDM_CPANEL_ABOUT + MENUITEM "Á¦¾îÆÇ Á¤º¸(&A)...", IDM_CPANEL_ABOUT END END @@ -284,9 +284,9 @@ IDS_CDBURN_AREA "Local Settings\\Application Data\\Microsoft\\CD Bur IDS_NEWFOLDER "»õ Æú´õ" -IDS_CPANEL_TITLE "Wine Control Panel" -IDS_CPANEL_NAME "Name" -IDS_CPANEL_DESCRIPTION "Description" +IDS_CPANEL_TITLE "Wine Á¦¾îÆÇ" +IDS_CPANEL_NAME "À̸§" +IDS_CPANEL_DESCRIPTION "¼³¸í" } STRINGTABLE diff --git a/dlls/shell32/shell32_No.rc b/dlls/shell32/shell32_No.rc index 0a8fc20dac7..82facc0458f 100644 --- a/dlls/shell32/shell32_No.rc +++ b/dlls/shell32/shell32_No.rc @@ -92,13 +92,13 @@ END MENU_CPANEL MENU BEGIN - POPUP "&File" + POPUP "&Fil" BEGIN MENUITEM SEPARATOR - MENUITEM "E&xit", IDM_CPANEL_EXIT + MENUITEM "&Avslutt", IDM_CPANEL_EXIT END - POPUP "&View" + POPUP "&Vis" BEGIN MENUITEM "&Store ikoner", FCIDM_SHVIEW_BIGICON MENUITEM "&Små ikoner", FCIDM_SHVIEW_SMALLICON @@ -106,9 +106,9 @@ BEGIN MENUITEM "&Detaljer", FCIDM_SHVIEW_REPORTVIEW END - POPUP "&Help" + POPUP "&Hjelp" BEGIN - MENUITEM "&About Control Panel...", IDM_CPANEL_ABOUT + MENUITEM "&Om Kontrollpanel...", IDM_CPANEL_ABOUT END END @@ -279,9 +279,9 @@ STRINGTABLE IDS_NEWFOLDER "Ny mappe" - IDS_CPANEL_TITLE "Wine Control Panel" - IDS_CPANEL_NAME "Name" - IDS_CPANEL_DESCRIPTION "Description" + IDS_CPANEL_TITLE "Wine Kontrollpanel" + IDS_CPANEL_NAME "Navn" + IDS_CPANEL_DESCRIPTION "Beskrivelse" } STRINGTABLE diff --git a/dlls/shell32/shell32_Ru.rc b/dlls/shell32/shell32_Ru.rc index b643cac0a10..795be24f8d0 100644 --- a/dlls/shell32/shell32_Ru.rc +++ b/dlls/shell32/shell32_Ru.rc @@ -93,13 +93,13 @@ END MENU_CPANEL MENU BEGIN - POPUP "&File" + POPUP "&Ôàéë" BEGIN MENUITEM SEPARATOR - MENUITEM "E&xit", IDM_CPANEL_EXIT + MENUITEM "Â&ûõîä", IDM_CPANEL_EXIT END - POPUP "&View" + POPUP "&Âèä" BEGIN MENUITEM "&Áîëüøèå çíà÷êè", FCIDM_SHVIEW_BIGICON MENUITEM "&Ìåëêèå çíà÷êè", FCIDM_SHVIEW_SMALLICON @@ -107,9 +107,9 @@ BEGIN MENUITEM "&Ïîäðîáíî", FCIDM_SHVIEW_REPORTVIEW END - POPUP "&Help" + POPUP "&Ñïðàâêà" BEGIN - MENUITEM "&About Control Panel...", IDM_CPANEL_ABOUT + MENUITEM "&Î Ïàíåëè Óïðàâëåíèÿ...", IDM_CPANEL_ABOUT END END @@ -209,7 +209,7 @@ STRINGTABLE IDS_DESKTOP "Ðàáî÷èé ñòîë" IDS_MYCOMPUTER "Ìîé êîìïüþòåð" IDS_RECYCLEBIN_FOLDER_NAME "Êîðçèíà" - IDS_CONTROLPANEL "Control Panel" + IDS_CONTROLPANEL "Ïàíåëü Óïðàâëåíèÿ" /* context menus */ IDS_VIEW_LARGE "&Áîëüøèå çíà÷êè" @@ -272,9 +272,9 @@ STRINGTABLE IDS_COMMON_VIDEO "Îáùèå äîêóìåíòû\\Ìîè ôèëüìû" IDS_CDBURN_AREA "Local Settings\\Application Data\\Microsoft\\CD Burning" - IDS_NEWFOLDER "New Folder" + IDS_NEWFOLDER "Íîâàÿ ïàïêà" - IDS_CPANEL_TITLE "Wine Control Panel" - IDS_CPANEL_NAME "Name" - IDS_CPANEL_DESCRIPTION "Description" + IDS_CPANEL_TITLE "Ïàíåëü Óïðàâëåíèÿ Wine" + IDS_CPANEL_NAME "Èìÿ" + IDS_CPANEL_DESCRIPTION "Îïèñàíèå" } diff --git a/dlls/shell32/shellpath.c b/dlls/shell32/shellpath.c index 362a25a06ca..77e027b8e1a 100644 --- a/dlls/shell32/shellpath.c +++ b/dlls/shell32/shellpath.c @@ -661,9 +661,6 @@ BOOL WINAPI PathQualifyAW(LPCVOID pszPath) return PathQualifyA(pszPath); } -/************************************************************************* - * PathResolveA [SHELL32.51] - */ BOOL WINAPI PathResolveA( LPSTR lpszPath, LPCSTR *alpszPaths, @@ -674,9 +671,6 @@ BOOL WINAPI PathResolveA( return 0; } -/************************************************************************* - * PathResolveW [SHELL32] - */ BOOL WINAPI PathResolveW( LPWSTR lpszPath, LPCWSTR *alpszPaths, @@ -1729,6 +1723,9 @@ cleanup: return hr; } +/************************************************************************* + * SHGetFolderPathAndSubDirW [SHELL32.@] + */ HRESULT WINAPI SHGetFolderPathAndSubDirW( HWND hwndOwner, /* [I] owner window */ int nFolder, /* [I] CSIDL identifying the folder */ diff --git a/dlls/shell32/tests/shlexec.c b/dlls/shell32/tests/shlexec.c index 644d611c11a..5eed12b2b17 100644 --- a/dlls/shell32/tests/shlexec.c +++ b/dlls/shell32/tests/shlexec.c @@ -847,9 +847,12 @@ static void test_find_executable(void) /* Don't test FindExecutable(..., NULL), it always crashes */ strcpy(command, "your word"); + if (0) /* Can crash on Vista! */ + { rc=(int)FindExecutableA(NULL, NULL, command); ok(rc == SE_ERR_FNF || rc > 32 /* nt4 */, "FindExecutable(NULL) returned %d\n", rc); ok(strcmp(command, "your word") != 0, "FindExecutable(NULL) returned command=[%s]\n", command); + } strcpy(command, "your word"); rc=(int)FindExecutableA(tmpdir, NULL, command); diff --git a/dlls/shell32/tests/shlfileop.c b/dlls/shell32/tests/shlfileop.c index 30d3f24fc7a..9b5220a5a44 100644 --- a/dlls/shell32/tests/shlfileop.c +++ b/dlls/shell32/tests/shlfileop.c @@ -319,14 +319,17 @@ static void test_delete(void) ok(file_exists("test1.txt"), "test1.txt should not have been removed\n"); /* try to delete an invalid filename */ - init_shfo_tests(); - shfo.pFrom = "\0"; - shfo.fFlags &= ~FOF_FILESONLY; - shfo.fAnyOperationsAborted = FALSE; - ret = SHFileOperation(&shfo); - ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret); - ok(!shfo.fAnyOperationsAborted, "Expected no aborted operations\n"); - ok(file_exists("test1.txt"), "Expected test1.txt to exist\n"); + if (0) { + /* this crashes on win9x */ + init_shfo_tests(); + shfo.pFrom = "\0"; + shfo.fFlags &= ~FOF_FILESONLY; + shfo.fAnyOperationsAborted = FALSE; + ret = SHFileOperation(&shfo); + ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret); + ok(!shfo.fAnyOperationsAborted, "Expected no aborted operations\n"); + ok(file_exists("test1.txt"), "Expected test1.txt to exist\n"); + } /* try an invalid function */ init_shfo_tests(); @@ -337,18 +340,22 @@ static void test_delete(void) ok(file_exists("test1.txt"), "Expected test1.txt to exist\n"); /* try an invalid list, only one null terminator */ - init_shfo_tests(); - shfo.pFrom = ""; - shfo.wFunc = FO_DELETE; - ret = SHFileOperation(&shfo); - ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret); - ok(file_exists("test1.txt"), "Expected test1.txt to exist\n"); + if (0) { + /* this crashes on win9x */ + init_shfo_tests(); + shfo.pFrom = ""; + shfo.wFunc = FO_DELETE; + ret = SHFileOperation(&shfo); + ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret); + ok(file_exists("test1.txt"), "Expected test1.txt to exist\n"); + } /* delete a dir, and then a file inside the dir, same as * deleting a nonexistent file */ init_shfo_tests(); shfo.pFrom = "testdir2\0testdir2\\one.txt\0"; + shfo.wFunc = FO_DELETE; ret = SHFileOperation(&shfo); ok(ret == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", ret); ok(!file_exists("testdir2"), "Expected testdir2 to not exist\n"); @@ -595,6 +602,8 @@ static void test_copy(void) init_shfo_tests(); shfo.pFrom = from; shfo.pTo = to; + /* suppress the error-dialog in win9x here */ + shfo.fFlags |= FOF_NOERRORUI; set_curr_dir_path(from, "test1.txt\0test2.txt\0"); set_curr_dir_path(to, "test3.txt\0"); retval = SHFileOperation(&shfo); @@ -604,6 +613,7 @@ static void test_copy(void) /* try to copy many files to nonexistent directory */ DeleteFile(to); + shfo.fFlags &= ~FOF_NOERRORUI; shfo.fAnyOperationsAborted = FALSE; retval = SHFileOperation(&shfo); ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval); @@ -956,32 +966,37 @@ static void test_copy(void) ok(DeleteFileA("two.txt"), "Expected file to exist\n"); ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n"); - createTestFile("one.txt"); - createTestFile("two.txt"); - - /* pTo contains bogus 2nd name longer than MAX_PATH, - * multiple source files, FOF_MULTIDESTFILES - * dest dir does not exist - */ - memset(to, 'a', 2 * MAX_PATH); - memset(to+MAX_PATH*2, 0, 2); - lstrcpyA(to, "threedir"); - shfo.pFrom = "one.txt\0two.txt\0"; - shfo.pTo = to; - shfo.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMATION | - FOF_SILENT | FOF_NOERRORUI; - retval = SHFileOperation(&shfo); - ok(retval == ERROR_CANCELLED || - retval == ERROR_SUCCESS, /* win2k3 */ - "Expected ERROR_CANCELLED or ERROR_SUCCESS, got %d\n", retval); - ok(!DeleteFileA("threedir\\one.txt"), "Expected file to not exist\n"); - ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n"); - ok(DeleteFileA("one.txt"), "Expected file to exist\n"); - ok(DeleteFileA("two.txt"), "Expected file to exist\n"); - ok(!RemoveDirectoryA("threedir"), "Expected dir to not exist\n"); + if (0) { + /* this crashes on win9x */ + createTestFile("one.txt"); + createTestFile("two.txt"); + + /* pTo contains bogus 2nd name longer than MAX_PATH, + * multiple source files, FOF_MULTIDESTFILES + * dest dir does not exist + */ + + memset(to, 'a', 2 * MAX_PATH); + memset(to+MAX_PATH*2, 0, 2); + lstrcpyA(to, "threedir"); + shfo.pFrom = "one.txt\0two.txt\0"; + shfo.pTo = to; + shfo.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMATION | + FOF_SILENT | FOF_NOERRORUI; + retval = SHFileOperation(&shfo); + ok(retval == ERROR_CANCELLED || + retval == ERROR_SUCCESS, /* win2k3 */ + "Expected ERROR_CANCELLED or ERROR_SUCCESS, got %d\n", retval); + ok(!DeleteFileA("threedir\\one.txt"), "Expected file to not exist\n"); + ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n"); + ok(DeleteFileA("one.txt"), "Expected file to exist\n"); + ok(DeleteFileA("two.txt"), "Expected file to exist\n"); + ok(!RemoveDirectoryA("threedir"), "Expected dir to not exist\n"); + + /* file exists in win2k */ + DeleteFileA("threedir"); + } - /* file exists in win2k */ - DeleteFileA("threedir"); createTestFile("one.txt"); createTestFile("two.txt"); diff --git a/dlls/shlwapi/path.c b/dlls/shlwapi/path.c index d0d4e93c3bc..e06e027aa25 100644 --- a/dlls/shlwapi/path.c +++ b/dlls/shlwapi/path.c @@ -235,6 +235,7 @@ LPWSTR WINAPI PathCombineW(LPWSTR lpszDest, LPCWSTR lpszDir, LPCWSTR lpszFile) LPSTR WINAPI PathAddBackslashA(LPSTR lpszPath) { size_t iLen; + LPSTR prev = lpszPath; TRACE("(%s)\n",debugstr_a(lpszPath)); @@ -243,11 +244,15 @@ LPSTR WINAPI PathAddBackslashA(LPSTR lpszPath) if (iLen) { - lpszPath += iLen; - if (lpszPath[-1] != '\\') + do { + lpszPath = CharNextA(prev); + if (*lpszPath) + prev = lpszPath; + } while (*lpszPath); + if (*prev != '\\') { - *lpszPath++ = '\\'; - *lpszPath = '\0'; + *lpszPath++ = '\\'; + *lpszPath = '\0'; } } return lpszPath; diff --git a/dlls/shlwapi/tests/path.c b/dlls/shlwapi/tests/path.c index e6b6548247d..07257d70e1d 100644 --- a/dlls/shlwapi/tests/path.c +++ b/dlls/shlwapi/tests/path.c @@ -799,7 +799,7 @@ static void test_PathAppendA(void) static void test_PathCanonicalizeA(void) { - char dest[MAX_PATH]; + char dest[LONG_LEN + MAX_PATH]; char too_long[LONG_LEN]; BOOL res; diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index 7daffd9b0c0..c4522ebdad5 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -119,6 +119,7 @@ static const USER_DRIVER *load_driver(void) GET_USER_FUNC(SetWindowIcon); GET_USER_FUNC(SetWindowStyle); GET_USER_FUNC(SetWindowText); + GET_USER_FUNC(ShowWindow); GET_USER_FUNC(SysCommand); GET_USER_FUNC(WindowMessage); GET_USER_FUNC(WindowPosChanging); @@ -395,6 +396,11 @@ static void nulldrv_SetWindowText( HWND hwnd, LPCWSTR text ) { } +static UINT nulldrv_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) +{ + return swp; +} + static LRESULT nulldrv_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam ) { return -1; @@ -472,6 +478,7 @@ static USER_DRIVER null_driver = nulldrv_SetWindowIcon, nulldrv_SetWindowStyle, nulldrv_SetWindowText, + nulldrv_ShowWindow, nulldrv_SysCommand, nulldrv_WindowMessage, nulldrv_WindowPosChanging, @@ -726,6 +733,11 @@ static void loaderdrv_SetWindowText( HWND hwnd, LPCWSTR text ) load_driver()->pSetWindowText( hwnd, text ); } +static UINT loaderdrv_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) +{ + return load_driver()->pShowWindow( hwnd, cmd, rect, swp ); +} + static LRESULT loaderdrv_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam ) { return load_driver()->pSysCommand( hwnd, wparam, lparam ); @@ -807,6 +819,7 @@ static USER_DRIVER lazy_load_driver = loaderdrv_SetWindowIcon, loaderdrv_SetWindowStyle, loaderdrv_SetWindowText, + loaderdrv_ShowWindow, loaderdrv_SysCommand, loaderdrv_WindowMessage, loaderdrv_WindowPosChanging, diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c index b37b5dc56c0..dcf95507543 100644 --- a/dlls/user32/edit.c +++ b/dlls/user32/edit.c @@ -860,6 +860,24 @@ static LRESULT WINAPI EditWndProc_common( HWND hwnd, UINT msg, break; } + case WM_UNICHAR: + if (unicode) + { + if (wParam == UNICODE_NOCHAR) return TRUE; + if (wParam <= 0x000fffff) + { + if(wParam > 0xffff) /* convert to surrogates */ + { + wParam -= 0x10000; + EDIT_WM_Char(es, (wParam >> 10) + 0xd800); + EDIT_WM_Char(es, (wParam & 0x03ff) + 0xdc00); + } + else EDIT_WM_Char(es, wParam); + } + return 0; + } + break; + case WM_CLEAR: EDIT_WM_Clear(es); break; diff --git a/dlls/user32/tests/dde.c b/dlls/user32/tests/dde.c index 127b61d00ff..908d60a5924 100644 --- a/dlls/user32/tests/dde.c +++ b/dlls/user32/tests/dde.c @@ -1666,7 +1666,7 @@ static void test_DdeCreateStringHandle(void) ret = DdeInitializeW(&dde_inst, client_ddeml_callback, APPCMD_CLIENTONLY, 0); if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { - trace("Skipping the DDE test on a Win9x platform\n"); + skip("DdeInitialize is unimplemented\n"); return; } diff --git a/dlls/user32/tests/dialog.c b/dlls/user32/tests/dialog.c index 8bf3c290b95..ccb5e31eb5f 100644 --- a/dlls/user32/tests/dialog.c +++ b/dlls/user32/tests/dialog.c @@ -896,7 +896,8 @@ static void test_GetDlgItemText(void) ret = GetDlgItemTextA(NULL, 0, string, sizeof(string)/sizeof(string[0])); ok(!ret, "GetDlgItemText(NULL) shouldn't have succeeded\n"); - ok(string[0] == '\0', "string retrieved using GetDlgItemText should have been NULL terminated\n"); + ok(string[0] == '\0' || broken(!strcmp(string, "Overwrite Me")), + "string retrieved using GetDlgItemText should have been NULL terminated\n"); } static void test_DialogBoxParamA(void) @@ -906,12 +907,16 @@ static void test_DialogBoxParamA(void) SetLastError(0xdeadbeef); ret = DialogBoxParamA(GetModuleHandle(NULL), "IDD_DIALOG" , hwnd_invalid, 0 , 0); - ok(0 == ret, "DialogBoxParamA returned %d, expected 0\n", ret); - ok(ERROR_INVALID_WINDOW_HANDLE == GetLastError(),"got %d, expected ERROR_INVALID_WINDOW_HANDLE\n",GetLastError()); + ok(0 == ret || broken(ret == -1), "DialogBoxParamA returned %d, expected 0\n", ret); + ok(ERROR_INVALID_WINDOW_HANDLE == GetLastError() || + broken(GetLastError() == 0xdeadbeef), + "got %d, expected ERROR_INVALID_WINDOW_HANDLE\n",GetLastError()); SetLastError(0xdeadbeef); ret = DialogBoxParamA(GetModuleHandle(NULL), "RESOURCE_INVALID" , 0, 0, 0); ok(-1 == ret, "DialogBoxParamA returned %d, expected -1\n", ret); - ok(ERROR_RESOURCE_NAME_NOT_FOUND == GetLastError(),"got %d, expected ERROR_RESOURCE_NAME_NOT_FOUND\n",GetLastError()); + ok(ERROR_RESOURCE_NAME_NOT_FOUND == GetLastError() || + broken(GetLastError() == 0xdeadbeef), + "got %d, expected ERROR_RESOURCE_NAME_NOT_FOUND\n",GetLastError()); } static void test_DisabledDialogTest(void) diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index c2012d542d8..45087cf5526 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -231,13 +231,13 @@ static const struct message WmSWP_MoveSeq[] = { * SWP_NOZORDER is stripped by the logging code */ static const struct message WmSWP_ResizeNoZOrder[] = { - { WM_WINDOWPOSCHANGING, sent|wparam, 0/*SWP_NOZORDER*/ }, + { WM_WINDOWPOSCHANGING, sent|wparam, /*SWP_NOZORDER|*/SWP_NOACTIVATE }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_NCPAINT, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ - { WM_WINDOWPOSCHANGED, sent|wparam, /*SWP_NOZORDER|*/SWP_NOMOVE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam, /*SWP_NOZORDER|*/SWP_NOMOVE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ { WM_NCPAINT, sent|optional }, /* Win9x doesn't send it */ @@ -473,6 +473,9 @@ static const struct message WmShowRestoreMaxOverlappedSeq[] = { { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, + { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_ERASEBKGND, sent|optional }, { 0 } }; /* ShowWindow(SW_RESTORE) for a not visible minimized overlapped window */ @@ -499,6 +502,9 @@ static const struct message WmShowRestoreMinOverlappedSeq[] = { { WM_WINDOWPOSCHANGED, sent|wparam, SWP_STATECHANGED|SWP_FRAMECHANGED|SWP_NOCOPYBITS }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, + { WM_NCCALCSIZE, sent|wparam|optional, TRUE }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_ERASEBKGND, sent|optional }, { WM_ACTIVATE, sent|wparam, 1 }, { 0 } }; @@ -1290,6 +1296,7 @@ static const struct message WmModalDialogSeq[] = { { WM_ACTIVATE, sent|wparam, 0 }, { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|optional }, { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, @@ -4079,7 +4086,7 @@ static const struct message WmInitEndSession_4[] = { /* Sending undocumented 0x3B message with wparam = 0x80000001 */ static const struct message WmInitEndSession_5[] = { { 0x003B, sent }, - { WM_ENDSESSION, sent|defwinproc|wparam|lparam, 1, ENDSESSION_LOGOFF }, + { WM_ENDSESSION, sent|defwinproc/*|wparam*/|lparam, 1, ENDSESSION_LOGOFF }, { 0 } }; @@ -4089,14 +4096,19 @@ static const struct message WmZOrder[] = { { HCBT_ACTIVATE, hook }, { WM_WINDOWPOSCHANGING, sent|wparam, 3, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOREDRAW|SWP_NOMOVE|SWP_NOSIZE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE, 0 }, + { WM_GETTEXT, sent|optional }, + { WM_NCCALCSIZE, sent|wparam|optional, 1 }, { WM_ACTIVATEAPP, sent|wparam, 1, 0 }, { WM_NCACTIVATE, sent|wparam|lparam, 1, 0 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam|lparam, 1, 0 }, { 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_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_GETTEXT, sent|optional }, { 0 } }; @@ -4222,7 +4234,7 @@ static void test_messages(void) ok_sequence(WmSWP_MoveSeq, "SetWindowPos:Move", FALSE ); flush_events(); flush_sequence(); - SetWindowPos( hwnd, 0, 200, 200, 250, 250, SWP_NOZORDER ); + SetWindowPos( hwnd, 0, 200, 200, 250, 250, SWP_NOZORDER|SWP_NOACTIVATE ); ok_sequence(WmSWP_ResizeNoZOrder, "SetWindowPos:WmSWP_ResizeNoZOrder", FALSE ); flush_events(); flush_sequence(); @@ -4579,9 +4591,6 @@ static void test_setwindowpos(void) GetWindowRect(hwnd, &rc); expect(sysX, rc.right); expect(winY, rc.bottom); - GetClientRect(hwnd, &rc); - expect(sysX - 6, rc.right); - expect(winY - 25, rc.bottom); flush_events(); flush_sequence(); @@ -4592,10 +4601,6 @@ static void test_setwindowpos(void) GetWindowRect(hwnd, &rc); expect(sysX, rc.right); expect(winY, rc.bottom); - GetClientRect(hwnd, &rc); - expect(sysX - 6, rc.right); - expect(winY - 25, rc.bottom); - DestroyWindow(hwnd); } @@ -6697,8 +6702,16 @@ static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, trace("popup: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam); - /* explicitly ignore WM_GETICON message */ - if (message == WM_GETICON) return 0; + switch (message) + { + case WM_GETICON: + /* explicitly ignore WM_GETICON message */ + return 0; + case WM_QUERYENDSESSION: + case WM_ENDSESSION: + lParam &= ~0x01; /* Vista adds a 0x01 flag */ + break; + } msg.message = message; msg.flags = sent|wparam|lparam; @@ -9150,6 +9163,7 @@ static void test_quit_message(void) BOOL ret; /* test using PostQuitMessage */ + flush_events(); PostQuitMessage(0xbeef); ret = PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); @@ -9410,9 +9424,9 @@ static void test_TrackMouseEvent(void) static const struct message WmSetWindowRgn[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, { WM_NCCALCSIZE, sent|wparam, 1 }, - { WM_NCPAINT, sent }, /* wparam != 1 */ + { WM_NCPAINT, sent|optional }, /* wparam != 1 */ { WM_GETTEXT, sent|defwinproc|optional }, - { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ + { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 } @@ -9427,9 +9441,9 @@ static const struct message WmSetWindowRgn_no_redraw[] = { }; static const struct message WmSetWindowRgn_clear[] = { - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGING, sent/*|wparam*/, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE/*|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE only on some Windows versions */ }, { WM_NCCALCSIZE, sent|wparam, 1 }, - { WM_NCPAINT, sent }, /* wparam != 1 */ + { WM_NCPAINT, sent|optional }, /* wparam != 1 */ { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, @@ -9437,6 +9451,12 @@ static const struct message WmSetWindowRgn_clear[] = { { WM_NCPAINT, sent|optional }, /* wparam != 1 */ { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGING, sent|optional }, + { WM_NCCALCSIZE, sent|optional|wparam, 1 }, + { WM_NCPAINT, sent|optional }, /* wparam != 1 */ + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|optional|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 } @@ -9669,7 +9689,7 @@ static const struct message WmShowMaximized_2[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMAXIMIZED }, { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOMOVE }, - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_MOVE, sent|optional }, /* Win9x doesn't send it */ { WM_SIZE, sent|wparam|optional, SIZE_MAXIMIZED }, /* Win9x doesn't send it */ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED }, @@ -10074,8 +10094,9 @@ static const struct message SetActiveWindowSeq2[] = { 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_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|defwinproc }, @@ -10114,8 +10135,9 @@ static const struct message SetActiveWindowSeq4[] = { 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_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 1 }, { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|defwinproc }, @@ -10161,10 +10183,10 @@ static void test_SetActiveWindow(void) ok_sequence(SetActiveWindowSeq1, "SetActiveWindow(hwnd), hwnd visible", TRUE); flush_sequence(); - trace("SetActiveWindow(popup), hwnd visible, popup visble\n"); + trace("SetActiveWindow(popup), hwnd visible, popup visible\n"); ret = SetActiveWindow(popup); - ok( ret == hwnd, "Failed to SetActiveWindow(popup), popup visble\n"); - ok_sequence(SetActiveWindowSeq2, "SetActiveWindow(popup), hwnd visible, popup visble", TRUE); + ok( ret == hwnd, "Failed to SetActiveWindow(popup), popup visible\n"); + ok_sequence(SetActiveWindowSeq2, "SetActiveWindow(popup), hwnd visible, popup visible", TRUE); flush_sequence(); ShowWindow(hwnd, SW_HIDE); @@ -10177,10 +10199,10 @@ static void test_SetActiveWindow(void) ok_sequence(SetActiveWindowSeq3, "SetActiveWindow(hwnd), hwnd not visible", TRUE); flush_sequence(); - trace("SetActiveWindow(popup), hwnd not visible, popup not visble\n"); + trace("SetActiveWindow(popup), hwnd not visible, popup not visible\n"); ret = SetActiveWindow(popup); ok( ret == hwnd, "Failed to SetActiveWindow(popup)\n"); - ok_sequence(SetActiveWindowSeq4, "SetActiveWindow(popup), hwnd not visible, popup not visble", TRUE); + ok_sequence(SetActiveWindowSeq4, "SetActiveWindow(popup), hwnd not visible, popup not visible", TRUE); flush_sequence(); trace("done\n"); @@ -10544,7 +10566,7 @@ static const struct message wm_lb_click_0[] = { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent|parent }, { WM_IME_SETCONTEXT, sent|wparam|optional|parent, 0 }, - { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|defwinproc }, @@ -10882,6 +10904,7 @@ static void test_menu_messages(void) ok(hmenu != 0, "LoadMenuA error %u\n", GetLastError()); SetMenu(hwnd, hmenu); + SetForegroundWindow( hwnd ); set_menu_style(hmenu, MNS_NOTIFYBYPOS); style = get_menu_style(hmenu); diff --git a/dlls/user32/tests/resource.c b/dlls/user32/tests/resource.c index a8b6c08f3f6..e588524abee 100644 --- a/dlls/user32/tests/resource.c +++ b/dlls/user32/tests/resource.c @@ -40,7 +40,13 @@ static void test_LoadStringW(void) /* Check that the string which is returned by LoadStringW matches the string at the pointer returned by LoadStringW when called with buflen = 0 */ + SetLastError(0xdeadbeef); length1 = LoadStringW(hInst, 2, (WCHAR *) &resourcepointer, 0); /* get pointer to resource. */ + if (!length1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + win_skip( "LoadStringW not implemented\n" ); + return; + } length2 = LoadStringW(hInst, 2, returnedstringw, sizeof(returnedstringw) /sizeof(WCHAR)); /* get resource string */ ok(length2 > 0, "LoadStringW failed to load resource 2, ret %d, err %d\n", length2, GetLastError()); ok(length1 == length2, "LoadStringW returned different values dependent on buflen. ret1 %d, ret2 %d\n", @@ -114,7 +120,8 @@ static void test_LoadStringA (void) "LoadString failed: ret %d err %d\n", ret, GetLastError()); ret = LoadStringA(hInst, 0, buf, 0); - ok( ret == -1, "LoadStringA did not return -1 when called with buflen = 0, got %d, err %d\n", + ok( ret == -1 || broken(ret == 0), + "LoadStringA did not return -1 when called with buflen = 0, got %d, err %d\n", ret, GetLastError()); } diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index fc5a16dacbb..909686d5b4a 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -155,6 +155,7 @@ typedef struct tagUSER_DRIVER { void (*pSetWindowIcon)(HWND,UINT,HICON); void (*pSetWindowStyle)(HWND,DWORD); void (*pSetWindowText)(HWND,LPCWSTR); + UINT (*pShowWindow)(HWND,INT,RECT*,UINT); LRESULT (*pSysCommand)(HWND,WPARAM,LPARAM); LRESULT (*pWindowMessage)(HWND,UINT,WPARAM,LPARAM); void (*pWindowPosChanging)(HWND,HWND,UINT,const RECT *,const RECT *,RECT *); diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 2b7f620d886..7756ab0f064 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -1249,7 +1249,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos ); swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */ if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE; - SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag ); + SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right - newPos.left, + newPos.bottom - newPos.top, swFlag ); } /* Notify the parent window only */ diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index a05b5f756d8..2bbaab97d64 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -905,7 +905,8 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) if (!(old_style & WS_MINIMIZE)) swpFlags |= SWP_STATECHANGED; SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y, - GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) ); + wpl.ptMinPosition.x + GetSystemMetrics(SM_CXICON), + wpl.ptMinPosition.y + GetSystemMetrics(SM_CYICON) ); swpFlags |= SWP_NOCOPYBITS; break; @@ -919,7 +920,8 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) if (old_style & WS_MINIMIZE) WINPOS_ShowIconTitle( hwnd, FALSE ); if (!(old_style & WS_MAXIMIZE)) swpFlags |= SWP_STATECHANGED; - SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y ); + SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, + wpl.ptMaxPosition.x + size.x, wpl.ptMaxPosition.y + size.y ); break; case SW_SHOWNOACTIVATE: @@ -941,7 +943,8 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL); WIN_SetStyle( hwnd, WS_MAXIMIZE, 0 ); swpFlags |= SWP_STATECHANGED; - SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y ); + SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, + wpl.ptMaxPosition.x + size.x, wpl.ptMaxPosition.y + size.y ); break; } } @@ -952,9 +955,6 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect ) /* Restore to normal position */ *rect = wpl.rcNormalPosition; - rect->right -= rect->left; - rect->bottom -= rect->top; - break; } @@ -1046,6 +1046,8 @@ static BOOL show_window( HWND hwnd, INT cmd ) if (!IsWindow( hwnd )) return wasVisible; } + swp = USER_Driver->pShowWindow( hwnd, cmd, &newPos, swp ); + parent = GetAncestor( hwnd, GA_PARENT ); if (parent && !IsWindowVisible( parent ) && !(swp & SWP_STATECHANGED)) { @@ -1055,7 +1057,7 @@ static BOOL show_window( HWND hwnd, INT cmd ) } else SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top, - newPos.right, newPos.bottom, LOWORD(swp) ); + newPos.right - newPos.left, newPos.bottom - newPos.top, swp ); if (cmd == SW_HIDE) { diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 2de05bfce5d..4f0e8977841 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -637,88 +637,21 @@ static void shader_hw_sample(SHADER_OPCODE_ARG* arg, DWORD sampler_idx, const ch } } -static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { - IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader; - IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) shader->baseShader.device; - WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info; - WINED3DFORMAT fmt; - WINED3DFORMAT conversion_group; - IWineD3DBaseTextureImpl *texture; - UINT i; - BOOL recorded = FALSE; - DWORD sampler_idx; - DWORD hex_version = shader->baseShader.hex_version; - char reg[256]; - char writemask[6]; - - switch(arg->opcode->opcode) { - case WINED3DSIO_TEX: - if (hex_version < WINED3DPS_VERSION(2,0)) { - sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; - } else { - sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK; - } - break; - - case WINED3DSIO_TEXLDL: - FIXME("Add color fixup for vertex texture WINED3DSIO_TEXLDL\n"); - return; - - case WINED3DSIO_TEXDP3TEX: - case WINED3DSIO_TEXM3x3TEX: - case WINED3DSIO_TEXM3x3SPEC: - case WINED3DSIO_TEXM3x3VSPEC: - case WINED3DSIO_TEXBEM: - case WINED3DSIO_TEXREG2AR: - case WINED3DSIO_TEXREG2GB: - case WINED3DSIO_TEXREG2RGB: - sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; - break; - - default: - /* Not a texture sampling instruction, nothing to do */ - return; - }; - - texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler_idx]; - if(texture) { - fmt = texture->resource.format; - conversion_group = texture->baseTexture.shader_conversion_group; - } else { - fmt = WINED3DFMT_UNKNOWN; - conversion_group = WINED3DFMT_UNKNOWN; - } - - /* before doing anything, record the sampler with the format in the format conversion list, - * but check if it's not there already - */ - for(i = 0; i < shader->baseShader.num_sampled_samplers; i++) { - if(shader->baseShader.sampled_samplers[i] == sampler_idx) { - recorded = TRUE; - } - } - if(!recorded) { - shader->baseShader.sampled_samplers[shader->baseShader.num_sampled_samplers] = sampler_idx; - shader->baseShader.num_sampled_samplers++; - shader->baseShader.sampled_format[sampler_idx] = conversion_group; - } - - pshader_get_register_name(arg->shader, arg->dst, reg); - shader_arb_get_write_mask(arg, arg->dst, writemask); - if(strlen(writemask) == 0) strcpy(writemask, ".xyzw"); - +static void gen_color_correction(SHADER_BUFFER *buffer, const char *reg, const char *writemask, + const char *one, const char *two, WINED3DFORMAT fmt, + WineD3D_GL_Info *gl_info) { switch(fmt) { case WINED3DFMT_V8U8: case WINED3DFMT_V16U16: if(GL_SUPPORT(NV_TEXTURE_SHADER) || - (GL_SUPPORT(ATI_ENVMAP_BUMPMAP) && fmt == WINED3DFMT_V8U8)) { + (GL_SUPPORT(ATI_ENVMAP_BUMPMAP) && fmt == WINED3DFMT_V8U8)) { #if 0 /* The 3rd channel returns 1.0 in d3d, but 0.0 in gl. Fix this while we're at it :-) * disabled until an application that needs it is found because it causes unneeded * shader recompilation in some game */ if(strlen(writemask) >= 4) { - shader_addline(arg->buffer, "MOV %s.%c, one.z;\n", reg, writemask[3]); + shader_addline(buffer, "MOV %s.%c, %s;\n", reg, one); } #endif } else { @@ -727,17 +660,19 @@ static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { * all registers, do so, this saves an instruction. */ if(strlen(writemask) >= 5) { - shader_addline(arg->buffer, "MAD %s, %s, coefmul.x, -one;\n", reg, reg); + shader_addline(buffer, "MAD %s, %s, %s, -%s;\n", reg, reg, two, one); } else if(strlen(writemask) >= 3) { - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", + reg, writemask[1], reg, writemask[1], - reg, writemask[1]); - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + two, one); + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", reg, writemask[2], - reg, writemask[2]); + reg, writemask[2], + two, one); } else if(strlen(writemask) == 2) { - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", reg, writemask[1], - reg, writemask[1]); + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", reg, writemask[1], + reg, writemask[1], two, one); } } break; @@ -748,16 +683,19 @@ static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { * and a(X) is always 1.0. Cannot do a full conversion due to L(blue) */ if(strlen(writemask) >= 3) { - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", + reg, writemask[1], reg, writemask[1], - reg, writemask[1]); - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + two, one); + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", reg, writemask[2], - reg, writemask[2]); + reg, writemask[2], + two, one); } else if(strlen(writemask) == 2) { - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", reg, writemask[1], - reg, writemask[1]); + reg, writemask[1], + two, one); } } break; @@ -766,20 +704,22 @@ static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { if(strlen(writemask) >= 4) { /* Swap y and z (U and L), and do a sign conversion on x and the new y(V and U) */ - shader_addline(arg->buffer, "MOV TMP.g, %s.%c;\n", + shader_addline(buffer, "MOV TMP.g, %s.%c;\n", reg, writemask[2]); - shader_addline(arg->buffer, "MAD %s.%c%c, %s.%c%c, coefmul.x, -one;\n", + shader_addline(buffer, "MAD %s.%c%c, %s.%c%c, %s, -%s;\n", reg, writemask[1], writemask[1], - reg, writemask[1], writemask[3]); - shader_addline(arg->buffer, "MOV %s.%c, TMP.g;\n", reg, + reg, writemask[1], writemask[3], + two, one); + shader_addline(buffer, "MOV %s.%c, TMP.g;\n", reg, writemask[3]); } else if(strlen(writemask) == 3) { /* This is bad: We have VL, but we need VU */ FIXME("2 components sampled from a converted L6V5U5 texture\n"); } else { - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + shader_addline(buffer, "MAD %s.%c, %s.%c, %s, -%s;\n", + reg, writemask[1], reg, writemask[1], - reg, writemask[1]); + two, one); } } break; @@ -789,17 +729,17 @@ static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { /* Correct the sign in all channels */ switch(strlen(writemask)) { case 4: - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + shader_addline(buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", reg, writemask[3], reg, writemask[3]); /* drop through */ case 3: - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + shader_addline(buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", reg, writemask[2], reg, writemask[2]); /* drop through */ case 2: - shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + shader_addline(buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", reg, writemask[1], reg, writemask[1]); break; @@ -811,7 +751,7 @@ static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { case 5: default: - shader_addline(arg->buffer, "MAD %s, %s, coefmul.x, -one;\n", reg, reg); + shader_addline(buffer, "MAD %s, %s, coefmul.x, -one;\n", reg, reg); } } break; @@ -825,11 +765,11 @@ static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { * are swapped compared to d3d. So swap red and green. */ if(GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) { - shader_addline(arg->buffer, "SWZ %s, %s, %c, %c, 1, 0;\n", + shader_addline(buffer, "SWZ %s, %s, %c, %c, 1, 0;\n", reg, reg, writemask[2], writemask[1]); } else { if(strlen(writemask) == 5) { - shader_addline(arg->buffer, "MOV %s.%c, %s.%c;\n", + shader_addline(buffer, "MOV %s.%c, %s.%c;\n", reg, writemask[2], reg, writemask[4]); } else if(strlen(writemask) == 2) { /* Nothing to do */ @@ -846,6 +786,80 @@ static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { } } +static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { + IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) shader->baseShader.device; + WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info; + WINED3DFORMAT fmt; + WINED3DFORMAT conversion_group; + IWineD3DBaseTextureImpl *texture; + UINT i; + BOOL recorded = FALSE; + DWORD sampler_idx; + DWORD hex_version = shader->baseShader.hex_version; + char reg[256]; + char writemask[6]; + + switch(arg->opcode->opcode) { + case WINED3DSIO_TEX: + if (hex_version < WINED3DPS_VERSION(2,0)) { + sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; + } else { + sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK; + } + break; + + case WINED3DSIO_TEXLDL: + FIXME("Add color fixup for vertex texture WINED3DSIO_TEXLDL\n"); + return; + + case WINED3DSIO_TEXDP3TEX: + case WINED3DSIO_TEXM3x3TEX: + case WINED3DSIO_TEXM3x3SPEC: + case WINED3DSIO_TEXM3x3VSPEC: + case WINED3DSIO_TEXBEM: + case WINED3DSIO_TEXREG2AR: + case WINED3DSIO_TEXREG2GB: + case WINED3DSIO_TEXREG2RGB: + sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; + break; + + default: + /* Not a texture sampling instruction, nothing to do */ + return; + }; + + texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler_idx]; + if(texture) { + fmt = texture->resource.format; + conversion_group = texture->baseTexture.shader_conversion_group; + } else { + fmt = WINED3DFMT_UNKNOWN; + conversion_group = WINED3DFMT_UNKNOWN; + } + + /* before doing anything, record the sampler with the format in the format conversion list, + * but check if it's not there already + */ + for(i = 0; i < shader->baseShader.num_sampled_samplers; i++) { + if(shader->baseShader.sampled_samplers[i] == sampler_idx) { + recorded = TRUE; + } + } + if(!recorded) { + shader->baseShader.sampled_samplers[shader->baseShader.num_sampled_samplers] = sampler_idx; + shader->baseShader.num_sampled_samplers++; + shader->baseShader.sampled_format[sampler_idx] = conversion_group; + } + + pshader_get_register_name(arg->shader, arg->dst, reg); + shader_arb_get_write_mask(arg, arg->dst, writemask); + if(strlen(writemask) == 0) strcpy(writemask, ".xyzw"); + + gen_color_correction(arg->buffer, reg, writemask, "one", "coefmul.x", fmt, gl_info); + +} + static void pshader_gen_input_modifier_line ( IWineD3DBaseShader *iface, @@ -1840,10 +1854,17 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) { glEnable(GL_FRAGMENT_PROGRAM_ARB); checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);"); TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id); - } else if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { + } else { priv->current_fprogram_id = 0; - glDisable(GL_FRAGMENT_PROGRAM_ARB); - checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); + + if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && !priv->use_arbfp_fixed_func) { + /* Disable only if we're not using arbfp fixed function fragment processing. If this is used, + * keep GL_FRAGMENT_PROGRAM_ARB enabled, and the fixed function pipeline will bind the fixed function + * replacement shader + */ + glDisable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); + } } } @@ -2174,3 +2195,765 @@ const shader_backend_t arb_program_shader_backend = { shader_arb_generate_vshader, shader_arb_get_caps, }; + +/* ARB_fragment_program fixed function pipeline replacement definitions */ +#define ARB_FFP_CONST_TFACTOR 0 +#define ARB_FFP_CONST_CONSTANT(i) ((ARB_FFP_CONST_TFACTOR) + 1 + i) +#define ARB_FFP_CONST_BUMPMAT(i) ((ARB_FFP_CONST_CONSTANT(7)) + 1 + i) + +struct arbfp_ffp_desc +{ + struct ffp_desc parent; + GLuint shader; + unsigned int num_textures_used; +}; + +static void arbfp_enable(IWineD3DDevice *iface, BOOL enable) { + if(enable) { + glEnable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)"); + } else { + glDisable(GL_FRAGMENT_PROGRAM_ARB); + checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)"); + } +} + +static HRESULT arbfp_alloc(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + struct shader_arb_priv *priv; + /* Share private data between the shader backend and the pipeline replacement, if both + * are the arb implementation. This is needed to figure out wether ARBfp should be disabled + * if no pixel shader is bound or not + */ + if(This->shader_backend == &arb_program_shader_backend) { + This->fragment_priv = This->shader_priv; + } else { + This->fragment_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_arb_priv)); + if(!This->fragment_priv) return E_OUTOFMEMORY; + } + priv = (struct shader_arb_priv *) This->fragment_priv; + priv->fragment_shaders = hash_table_create(ffp_program_key_hash, ffp_program_key_compare); + priv->use_arbfp_fixed_func = TRUE; + return WINED3D_OK; +} + +static void arbfp_free_ffpshader(void *value, void *gli) { + WineD3D_GL_Info *gl_info = gli; + struct arbfp_ffp_desc *entry_arb = value; + + ENTER_GL(); + GL_EXTCALL(glDeleteProgramsARB(1, &entry_arb->shader)); + checkGLcall("glDeleteProgramsARB(1, &entry_arb->shader)"); + HeapFree(GetProcessHeap(), 0, entry_arb); + LEAVE_GL(); +} + +static void arbfp_free(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; + struct shader_arb_priv *priv = (struct shader_arb_priv *) This->fragment_priv; + + hash_table_destroy(priv->fragment_shaders, arbfp_free_ffpshader, &This->adapter->gl_info); + priv->use_arbfp_fixed_func = FALSE; + + if(This->shader_backend != &arb_program_shader_backend) { + HeapFree(GetProcessHeap(), 0, This->fragment_priv); + } +} + +static void arbfp_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct fragment_caps *caps) { + caps->TextureOpCaps = WINED3DTEXOPCAPS_DISABLE | + WINED3DTEXOPCAPS_SELECTARG1 | + WINED3DTEXOPCAPS_SELECTARG2 | + WINED3DTEXOPCAPS_MODULATE4X | + WINED3DTEXOPCAPS_MODULATE2X | + WINED3DTEXOPCAPS_MODULATE | + WINED3DTEXOPCAPS_ADDSIGNED2X | + WINED3DTEXOPCAPS_ADDSIGNED | + WINED3DTEXOPCAPS_ADD | + WINED3DTEXOPCAPS_SUBTRACT | + WINED3DTEXOPCAPS_ADDSMOOTH | + WINED3DTEXOPCAPS_BLENDCURRENTALPHA | + WINED3DTEXOPCAPS_BLENDFACTORALPHA | + WINED3DTEXOPCAPS_BLENDTEXTUREALPHA | + WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA | + WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM | + WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR | + WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA | + WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA | + WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR | + WINED3DTEXOPCAPS_DOTPRODUCT3 | + WINED3DTEXOPCAPS_MULTIPLYADD | + WINED3DTEXOPCAPS_LERP | + WINED3DTEXOPCAPS_BUMPENVMAP; + + /* TODO: Implement WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE + and WINED3DTEXOPCAPS_PREMODULATE */ + + caps->MaxTextureBlendStages = 8; + caps->MaxSimultaneousTextures = min(GL_LIMITS(fragment_samplers), 8); + + caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP; +} +#undef GLINFO_LOCATION + +#define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info +static void state_texfactor_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + float col[4]; + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; + + /* Do not overwrite pixel shader constants if a pshader is in use */ + if(use_ps(device)) return; + + D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col); + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_TFACTOR, col)); + checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_TFACTOR, col)"); + + if(device->shader_backend == &arb_program_shader_backend) { + device = stateblock->wineD3DDevice; + device->activeContext->pshader_const_dirty[ARB_FFP_CONST_TFACTOR] = 1; + device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_TFACTOR + 1); + } +} + +static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; + float mat[2][2]; + + if(use_ps(device)) { + if(stage != 0 && + ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) { + /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled + * anyway + */ + if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT)) { + device->StateTable[STATE_PIXELSHADERCONSTANT].apply(STATE_PIXELSHADERCONSTANT, stateblock, context); + } + } + /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */ + return; + } + + mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]); + mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]); + mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]); + mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]); + + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_BUMPMAT(stage), &mat[0][0])); + checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_BUMPMAT(stage), &mat[0][0])"); + + if(device->shader_backend == &arb_program_shader_backend) { + device->activeContext->pshader_const_dirty[ARB_FFP_CONST_BUMPMAT(stage)] = 1; + device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_BUMPMAT(stage) + 1); + } +} + +static const char *get_argreg(SHADER_BUFFER *buffer, DWORD argnum, unsigned int stage, DWORD arg) { + const char *ret; + + if(arg > WINED3DTOP_LERP) return "unused"; /* This is the marker for unused registers */ + + switch(arg & WINED3DTA_SELECTMASK) { + case WINED3DTA_DIFFUSE: + ret = "fragment.color.primary"; break; + + case WINED3DTA_CURRENT: + if(stage == 0) ret = "fragment.color.primary"; + else ret = "ret"; + break; + + case WINED3DTA_TEXTURE: + switch(stage) { + case 0: ret = "tex0"; break; + case 1: ret = "tex1"; break; + case 2: ret = "tex2"; break; + case 3: ret = "tex3"; break; + case 4: ret = "tex4"; break; + case 5: ret = "tex5"; break; + case 6: ret = "tex6"; break; + case 7: ret = "tex7"; break; + default: ret = "unknown texture"; + } + break; + + case WINED3DTA_TFACTOR: + ret = "tfactor"; break; + + case WINED3DTA_SPECULAR: + ret = "fragment.color.secondary"; break; + + case WINED3DTA_TEMP: + ret = "tempreg"; break; + + case WINED3DTA_CONSTANT: + FIXME("Implement perstage constants\n"); + switch(stage) { + case 0: ret = "const0"; break; + case 1: ret = "const1"; break; + case 2: ret = "const2"; break; + case 3: ret = "const3"; break; + case 4: ret = "const4"; break; + case 5: ret = "const5"; break; + case 6: ret = "const6"; break; + case 7: ret = "const7"; break; + } + default: + return "unknown"; + } + + if(arg & WINED3DTA_COMPLEMENT) { + shader_addline(buffer, "SUB arg%u, const.x, %s;\n", argnum, ret); + if(argnum == 0) ret = "arg0"; + if(argnum == 1) ret = "arg1"; + if(argnum == 2) ret = "arg2"; + } + return ret; +} + +static void gen_ffp_instr(SHADER_BUFFER *buffer, unsigned int stage, BOOL color, BOOL alpha, BOOL last, + DWORD dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2) { + const char *dstmask, *dstreg, *arg0, *arg1, *arg2; + unsigned int mul = 1; + BOOL mul_final_dest = FALSE; + + if(color && alpha) dstmask = ""; + else if(color) dstmask = ".rgb"; + else dstmask = ".a"; + + if(dst == tempreg && last) FIXME("Last texture stage writes to D3DTA_TEMP\n"); + if(dst == tempreg) dstreg = "tempreg"; + else if(last) dstreg = "result.color"; + else dstreg = "ret"; + + arg0 = get_argreg(buffer, 0, stage, dw_arg0); + arg1 = get_argreg(buffer, 1, stage, dw_arg1); + arg2 = get_argreg(buffer, 2, stage, dw_arg2); + + switch(op) { + case WINED3DTOP_DISABLE: + if(stage == 1) shader_addline(buffer, "MOV %s%s, fragment.color.primary;\n", dstreg, dstmask); + break; + + case WINED3DTOP_SELECTARG2: + arg1 = arg2; + case WINED3DTOP_SELECTARG1: + shader_addline(buffer, "MOV %s%s, %s;\n", dstreg, dstmask, arg1); + break; + + case WINED3DTOP_MODULATE4X: + mul = 2; + case WINED3DTOP_MODULATE2X: + mul *= 2; + if(strcmp(dstreg, "result.color") == 0) { + dstreg = "ret"; + mul_final_dest = TRUE; + } + case WINED3DTOP_MODULATE: + shader_addline(buffer, "MUL %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2); + break; + + case WINED3DTOP_ADDSIGNED2X: + mul = 2; + if(strcmp(dstreg, "result.color") == 0) { + dstreg = "ret"; + mul_final_dest = TRUE; + } + case WINED3DTOP_ADDSIGNED: + shader_addline(buffer, "SUB arg2, %s, const.w;\n", arg2); + arg2 = "arg2"; + case WINED3DTOP_ADD: + shader_addline(buffer, "ADD %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2); + break; + + case WINED3DTOP_SUBTRACT: + shader_addline(buffer, "SUB %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2); + break; + + case WINED3DTOP_ADDSMOOTH: + shader_addline(buffer, "SUB arg1, const.x, %s;\n", arg1); + shader_addline(buffer, "MAD %s%s, arg1, %s, %s;\n", dstreg, dstmask, arg2, arg1); + break; + + case WINED3DTOP_BLENDCURRENTALPHA: + arg0 = get_argreg(buffer, 0, stage, WINED3DTA_CURRENT); + shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2); + break; + case WINED3DTOP_BLENDFACTORALPHA: + arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TFACTOR); + shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2); + break; + case WINED3DTOP_BLENDTEXTUREALPHA: + arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE); + shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2); + break; + case WINED3DTOP_BLENDDIFFUSEALPHA: + arg0 = get_argreg(buffer, 0, stage, WINED3DTA_DIFFUSE); + shader_addline(buffer, "LRP %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2); + break; + + case WINED3DTOP_BLENDTEXTUREALPHAPM: + shader_addline(buffer, "SUB arg0.a, const.x, %s;\n", arg1); + shader_addline(buffer, "MAD %s%s, %s, arg0.a, %s;\n", dstreg, dstmask, arg2, arg1); + break; + + /* D3DTOP_PREMODULATE ???? */ + + case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: + shader_addline(buffer, "SUB arg0.a, const.x, %s;\n", arg1); + shader_addline(buffer, "MAD %s%s, arg0.a, %s, %s;\n", dstreg, dstmask, arg2, arg1); + break; + case WINED3DTOP_MODULATEALPHA_ADDCOLOR: + shader_addline(buffer, "MAD %s%s, %s.a, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg1); + break; + case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: + shader_addline(buffer, "SUB arg0, const.x, %s;\n", arg1); + shader_addline(buffer, "MAD %s%s, arg0, %s, %s.a;\n", dstreg, dstmask, arg2, arg1); + break; + case WINED3DTOP_MODULATECOLOR_ADDALPHA: + shader_addline(buffer, "MAD %s%s, %s, %s, %s.a;\n", dstreg, dstmask, arg1, arg2, arg1); + break; + + case WINED3DTOP_DOTPRODUCT3: + mul = 4; + if(strcmp(dstreg, "result.color") == 0) { + dstreg = "ret"; + mul_final_dest = TRUE; + } + shader_addline(buffer, "SUB arg1, %s, const.w;\n", arg1); + shader_addline(buffer, "SUB arg2, %s, const.w;\n", arg2); + shader_addline(buffer, "DP3 %s%s, arg1, arg2;\n", dstreg, dstmask); + break; + + case WINED3DTOP_MULTIPLYADD: + shader_addline(buffer, "MAD %s%s, %s, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg0); + break; + + case WINED3DTOP_LERP: + /* The msdn is not quite right here */ + shader_addline(buffer, "LRP %s%s, %s, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2); + break; + + case WINED3DTOP_BUMPENVMAP: + case WINED3DTOP_BUMPENVMAPLUMINANCE: + /* Those are handled in the first pass of the shader(generation pass 1 and 2) already */ + break; + + default: + FIXME("Unhandled texture op %08x\n", op); + } + + if(mul == 2) { + shader_addline(buffer, "MUL %s%s, %s, const.y;\n", mul_final_dest ? "result.color" : dstreg, dstmask, dstreg); + } else if(mul == 4) { + shader_addline(buffer, "MUL %s%s, %s, const.z;\n", mul_final_dest ? "result.color" : dstreg, dstmask, dstreg); + } +} + +/* The stateblock is passed for GLINFO_LOCATION */ +static GLuint gen_arbfp_ffp_shader(struct ffp_settings *settings, IWineD3DStateBlockImpl *stateblock) { + unsigned int stage; + SHADER_BUFFER buffer; + BOOL tex_read[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}; + BOOL bump_used[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE}; + const char *textype; + const char *instr; + char colorcor_dst[8]; + GLuint ret; + DWORD arg0, arg1, arg2; + BOOL tempreg_used = FALSE, tfactor_used = FALSE; + BOOL last = FALSE; + + /* Find out which textures are read */ + for(stage = 0; stage < MAX_TEXTURES; stage++) { + if(settings->op[stage].cop == WINED3DTOP_DISABLE) break; + arg0 = settings->op[stage].carg0 & WINED3DTA_SELECTMASK; + arg1 = settings->op[stage].carg1 & WINED3DTA_SELECTMASK; + arg2 = settings->op[stage].carg2 & WINED3DTA_SELECTMASK; + if(arg0 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + if(arg1 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + if(arg2 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + + if(settings->op[stage].cop == WINED3DTOP_BLENDTEXTUREALPHA) tex_read[stage] = TRUE; + if(settings->op[stage].cop == WINED3DTOP_BUMPENVMAP) { + bump_used[stage] = TRUE; + tex_read[stage] = TRUE; + } + if(settings->op[stage].cop == WINED3DTOP_BUMPENVMAPLUMINANCE) { + bump_used[stage] = TRUE; + tex_read[stage] = TRUE; + } + + if(arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) { + tfactor_used = TRUE; + } + + if(settings->op[stage].dst == tempreg) tempreg_used = TRUE; + if(arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) { + tempreg_used = TRUE; + } + + if(settings->op[stage].aop == WINED3DTOP_DISABLE) continue; + arg0 = settings->op[stage].aarg0 & WINED3DTA_SELECTMASK; + arg1 = settings->op[stage].aarg1 & WINED3DTA_SELECTMASK; + arg2 = settings->op[stage].aarg2 & WINED3DTA_SELECTMASK; + if(arg0 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + if(arg1 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + if(arg2 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE; + + if(arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) { + tempreg_used = TRUE; + } + if(arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) { + tfactor_used = TRUE; + } + } + + /* Shader header */ + buffer.bsize = 0; + buffer.lineNo = 0; + buffer.newline = TRUE; + buffer.buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SHADER_PGMSIZE); + + shader_addline(&buffer, "!!ARBfp1.0\n"); + + switch(settings->fog) { + case FOG_OFF: break; + case FOG_LINEAR: shader_addline(&buffer, "OPTION ARB_fog_linear;\n"); break; + case FOG_EXP: shader_addline(&buffer, "OPTION ARB_fog_exp;\n"); break; + case FOG_EXP2: shader_addline(&buffer, "OPTION ARB_fog_exp2;\n"); break; + default: FIXME("Unexpected fog setting %d\n", settings->fog); + } + + shader_addline(&buffer, "PARAM const = {1, 2, 4, 0.5};\n"); + shader_addline(&buffer, "TEMP ret;\n"); + if(tempreg_used) shader_addline(&buffer, "TEMP tempreg;\n"); + shader_addline(&buffer, "TEMP arg0;\n"); + shader_addline(&buffer, "TEMP arg1;\n"); + shader_addline(&buffer, "TEMP arg2;\n"); + for(stage = 0; stage < MAX_TEXTURES; stage++) { + if(!tex_read[stage]) continue; + shader_addline(&buffer, "TEMP tex%u;\n", stage); + if(!bump_used[stage]) continue; + shader_addline(&buffer, "PARAM bumpmat%u = program.env[%u];\n", stage, ARB_FFP_CONST_BUMPMAT(stage)); + } + if(tfactor_used) { + shader_addline(&buffer, "PARAM tfactor = program.env[%u];\n", ARB_FFP_CONST_TFACTOR); + } + + /* Generate texture sampling instructions) */ + for(stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3DTOP_DISABLE; stage++) { + if(!tex_read[stage]) continue; + + switch(settings->op[stage].tex_type) { + case tex_1d: textype = "1D"; break; + case tex_2d: textype = "2D"; break; + case tex_3d: textype = "3D"; break; + case tex_cube: textype = "CUBE"; break; + case tex_rect: textype = "RECT"; break; + default: textype = "unexpected_textype"; break; + } + + if(settings->op[stage].projected == proj_none) { + instr = "TEX"; + } else if(settings->op[stage].projected == proj_count4) { + instr = "TXP"; + } else { + instr = "TXP"; + ERR("Implement proj_count3\n"); + } + + if(stage > 0 && + (settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAP || + settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE)) { + shader_addline(&buffer, "SWZ arg1, bumpmat%u, x, z, 0, 0;\n", stage - 1); + shader_addline(&buffer, "DP3 ret.r, arg1, tex%u;\n", stage - 1); + shader_addline(&buffer, "SWZ arg1, bumpmat%u, y, w, 0, 0;\n", stage - 1); + shader_addline(&buffer, "DP3 ret.g, arg1, tex%u;\n", stage - 1); + shader_addline(&buffer, "ADD ret, ret, fragment.texcoord[%u];\n", stage); + shader_addline(&buffer, "%s tex%u, ret, texture[%u], %s;\n", + instr, stage, stage, textype); + } else { + shader_addline(&buffer, "%s tex%u, fragment.texcoord[%u], texture[%u], %s;\n", + instr, stage, stage, stage, textype); + } + + sprintf(colorcor_dst, "tex%u", stage); + gen_color_correction(&buffer, colorcor_dst, ".rgba", "const.x", "const.y", + settings->op[stage].color_correction, &GLINFO_LOCATION); + } + + /* Generate the main shader */ + for(stage = 0; stage < MAX_TEXTURES; stage++) { + if(settings->op[stage].cop == WINED3DTOP_DISABLE) { + if(stage == 0) { + shader_addline(&buffer, "MOV result.color, fragment.color.primary;\n"); + } + break; + } else if(stage == (MAX_TEXTURES - 1)) { + last = TRUE; + } else if(settings->op[stage + 1].cop == WINED3DTOP_DISABLE) { + last = TRUE; + } + + if(settings->op[stage].aop == WINED3DTOP_DISABLE) { + gen_ffp_instr(&buffer, stage, TRUE, FALSE, last, settings->op[stage].dst, + settings->op[stage].cop, settings->op[stage].carg0, + settings->op[stage].carg1, settings->op[stage].carg2); + if(last && stage == 0) { + shader_addline(&buffer, "MOV result.color.a, fragment.color.primary.a;\n"); + } else if(last) { + shader_addline(&buffer, "MOV result.color.a, ret.a;\n"); + } else if(stage == 0) { + shader_addline(&buffer, "MOV ret.a, fragment.color.primary.a;\n"); + } + } else if(settings->op[stage].aop == settings->op[stage].cop && + settings->op[stage].carg0 == settings->op[stage].aarg0 && + settings->op[stage].carg1 == settings->op[stage].aarg1 && + settings->op[stage].carg2 == settings->op[stage].aarg2) { + gen_ffp_instr(&buffer, stage, TRUE, TRUE, last, settings->op[stage].dst, + settings->op[stage].cop, settings->op[stage].carg0, + settings->op[stage].carg1, settings->op[stage].carg2); + } else { + gen_ffp_instr(&buffer, stage, TRUE, FALSE, last, settings->op[stage].dst, + settings->op[stage].cop, settings->op[stage].carg0, + settings->op[stage].carg1, settings->op[stage].carg2); + gen_ffp_instr(&buffer, stage, FALSE, TRUE, last, settings->op[stage].dst, + settings->op[stage].aop, settings->op[stage].aarg0, + settings->op[stage].aarg1, settings->op[stage].aarg2); + } + } + + /* TODO: Generate sRGB write color correction */ + + /* Footer */ + shader_addline(&buffer, "END\n"); + + /* Generate the shader */ + GL_EXTCALL(glGenProgramsARB(1, &ret)); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ret)); + GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(buffer.buffer), buffer.buffer)); + + if (glGetError() == GL_INVALID_OPERATION) { + GLint pos; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); + FIXME("Vertex program error at position %d: %s\n", pos, + debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + } + return ret; +} + +static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + IWineD3DDeviceImpl *device = stateblock->wineD3DDevice; + struct shader_arb_priv *priv = (struct shader_arb_priv *) device->fragment_priv; + BOOL use_pshader = use_ps(device); + BOOL use_vshader = use_vs(device); + struct ffp_settings settings; + struct arbfp_ffp_desc *desc; + unsigned int i; + + if(isStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE))) return; + + if(use_pshader) { + IWineD3DPixelShader_CompileShader(stateblock->pixelShader); + } else { + /* Find or create a shader implementing the fixed function pipeline settings, then activate it */ + gen_ffp_op(stateblock, &settings, FALSE); + desc = (struct arbfp_ffp_desc *) find_ffp_shader(priv->fragment_shaders, &settings); + if(!desc) { + desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*desc)); + if(!desc) { + ERR("Out of memory\n"); + return; + } + desc->num_textures_used = 0; + for(i = 0; i < GL_LIMITS(texture_stages); i++) { + if(settings.op[i].cop == WINED3DTOP_DISABLE) break; + desc->num_textures_used = i; + } + + memcpy(&desc->parent.settings, &settings, sizeof(settings)); + desc->shader = gen_arbfp_ffp_shader(&settings, stateblock); + add_ffp_shader(priv->fragment_shaders, &desc->parent); + TRACE("Allocated fixed function replacement shader descriptor %p\n", desc); + } + + /* Now activate the replacement program. GL_FRAGMENT_PROGRAM_ARB is already active(however, note the + * comment above the shader_select call below). If e.g. GLSL is active, the shader_select call will + * deactivate it. + */ + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, desc->shader)); + checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, desc->shader)"); + + if(device->shader_backend == &arb_program_shader_backend && context->last_was_pshader) { + /* Reload fixed function constants since they collide with the pixel shader constants */ + for(i = 0; i < MAX_TEXTURES; i++) { + set_bumpmat_arbfp(STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT00), stateblock, context); + } + state_texfactor_arbfp(STATE_RENDER(WINED3DRS_TEXTUREFACTOR), stateblock, context); + } + } + + /* Finally, select the shader. If a pixel shader is used, it will be set and enabled by the shader backend. + * If this shader backend is arbfp(most likely), then it will simply overwrite the last fixed function replace- + * ment shader. If the shader backend is not ARB, it currently is important that the opengl implementation + * type overwrites GL_ARB_fragment_program. This is currently the case with GLSL. If we really want to use + * atifs or nvrc pixel shaders with arb fragment programs we'd have to disable GL_FRAGMENT_PROGRAM_ARB here + * + * Don't call shader_select if the vertex shader is dirty, because some shader backends(GLSL) need both shaders + * to be compiled before activating them(needs some cleanups in the shader backend interface) + */ + if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) { + device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader); + + if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) { + device->StateTable[STATE_VERTEXSHADERCONSTANT].apply(STATE_VERTEXSHADERCONSTANT, stateblock, context); + } + } + context->last_was_pshader = use_pshader; + if(use_pshader) { + device->StateTable[STATE_PIXELSHADERCONSTANT].apply(STATE_PIXELSHADERCONSTANT, stateblock, context); + } +} + +/* We can't link the fog states to the fragment state directly since the vertex pipeline links them + * to FOGENABLE. A different linking in different pipeline parts can't be expressed in the combined + * state table, so we need to handle that with a forwarding function. The other invisible side effect + * is that changing the fog start and fog end(which links to FOGENABLE in vertex) results in the + * fragment_prog_arbfp function being called because FOGENABLE is dirty, which calls this function here + */ +static void state_arbfp_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + if(!isStateDirty(context, STATE_PIXELSHADER)) { + fragment_prog_arbfp(state, stateblock, context); + } +} + +#undef GLINFO_LOCATION + +static const struct StateEntryTemplate arbfp_fragmentstate_template[] = { + {STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), set_bumpmat_arbfp }, 0 }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, 0 }, + { STATE_PIXELSHADER, { STATE_PIXELSHADER, fragment_prog_arbfp }, 0 }, + { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_arbfp_fog }, 0 }, + {0 /* Terminate */, { 0, 0 }, 0 }, +}; + +const struct fragment_pipeline arbfp_fragment_pipeline = { + arbfp_enable, + arbfp_get_caps, + arbfp_alloc, + arbfp_free, + arbfp_fragmentstate_template +}; diff --git a/dlls/wined3d/ati_fragment_shader.c b/dlls/wined3d/ati_fragment_shader.c index 8989aa6541b..54b05b144c1 100644 --- a/dlls/wined3d/ati_fragment_shader.c +++ b/dlls/wined3d/ati_fragment_shader.c @@ -50,7 +50,7 @@ struct atifs_ffp_desc struct atifs_private_data { - struct list fragment_shaders; /* A linked list to track fragment pipeline replacement shaders */ + hash_table_t *fragment_shaders; /* A hashtable to track fragment pipeline replacement shaders */ }; @@ -226,7 +226,7 @@ static GLuint find_tmpreg(struct texture_stage_op op[MAX_TEXTURES]) { lowest_read = i; } - if(lowest_write == -1 && op[i].dst == WINED3DTA_TEMP) { + if(lowest_write == -1 && op[i].dst == tempreg) { lowest_write = i; } @@ -418,7 +418,7 @@ static GLuint gen_ati_shader(struct texture_stage_op op[MAX_TEXTURES], WineD3D_G break; } - if(op[stage].dst == WINED3DTA_TEMP) { + if(op[stage].dst == tempreg) { /* If we're writing to D3DTA_TEMP, but never reading from it we don't have to write there in the first place. * skip the entire stage, this saves some GPU time */ @@ -780,13 +780,13 @@ static GLuint gen_ati_shader(struct texture_stage_op op[MAX_TEXTURES], WineD3D_G static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { IWineD3DDeviceImpl *This = stateblock->wineD3DDevice; struct atifs_ffp_desc *desc; - struct texture_stage_op op[MAX_TEXTURES]; + struct ffp_settings settings; struct atifs_private_data *priv = (struct atifs_private_data *) This->fragment_priv; DWORD mapped_stage; unsigned int i; - gen_ffp_op(stateblock, op); - desc = (struct atifs_ffp_desc *) find_ffp_shader(&priv->fragment_shaders, op); + gen_ffp_op(stateblock, &settings, TRUE); + desc = (struct atifs_ffp_desc *) find_ffp_shader(priv->fragment_shaders, &settings); if(!desc) { desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*desc)); if(!desc) { @@ -795,13 +795,13 @@ static void set_tex_op_atifs(DWORD state, IWineD3DStateBlockImpl *stateblock, Wi } desc->num_textures_used = 0; for(i = 0; i < GL_LIMITS(texture_stages); i++) { - if(op[i].cop == WINED3DTOP_DISABLE) break; + if(settings.op[i].cop == WINED3DTOP_DISABLE) break; desc->num_textures_used = i; } - memcpy(desc->parent.op, op, sizeof(op)); - desc->shader = gen_ati_shader(op, &GLINFO_LOCATION); - add_ffp_shader(&priv->fragment_shaders, &desc->parent); + memcpy(&desc->parent.settings, &settings, sizeof(settings)); + desc->shader = gen_ati_shader(settings.op, &GLINFO_LOCATION); + add_ffp_shader(priv->fragment_shaders, &desc->parent); TRACE("Allocated fixed function replacement shader descriptor %p\n", desc); } @@ -1036,26 +1036,28 @@ static HRESULT atifs_alloc(IWineD3DDevice *iface) { return E_OUTOFMEMORY; } priv = (struct atifs_private_data *) This->fragment_priv; - list_init(&priv->fragment_shaders); + priv->fragment_shaders = hash_table_create(ffp_program_key_hash, ffp_program_key_compare); return WINED3D_OK; } #define GLINFO_LOCATION This->adapter->gl_info +static void atifs_free_ffpshader(void *value, void *device) { + IWineD3DDeviceImpl *This = device; + struct atifs_ffp_desc *entry_ati = value; + + ENTER_GL(); + GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader)); + checkGLcall("glDeleteFragmentShaderATI(entry->shader)"); + HeapFree(GetProcessHeap(), 0, entry_ati); + LEAVE_GL(); +} + static void atifs_free(IWineD3DDevice *iface) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; struct atifs_private_data *priv = (struct atifs_private_data *) This->fragment_priv; - struct ffp_desc *entry, *entry2; - struct atifs_ffp_desc *entry_ati; - ENTER_GL(); - LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &priv->fragment_shaders, struct ffp_desc, entry) { - entry_ati = (struct atifs_ffp_desc *) entry; - GL_EXTCALL(glDeleteFragmentShaderATI(entry_ati->shader)); - checkGLcall("glDeleteFragmentShaderATI(entry->shader)"); - list_remove(&entry->entry); - HeapFree(GetProcessHeap(), 0, entry); - } - LEAVE_GL(); + hash_table_destroy(priv->fragment_shaders, atifs_free_ffpshader, This); + HeapFree(GetProcessHeap(), 0, priv); This->fragment_priv = NULL; } diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index ca81f3a5aca..bb354f67d6f 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -538,9 +538,6 @@ WineD3DContext *CreateContext(IWineD3DDeviceImpl *This, IWineD3DSurfaceImpl *tar checkGLcall("glEnable(GL_WEIGHT_SUM_UNITY_ARB)"); } if(GL_SUPPORT(NV_TEXTURE_SHADER2)) { - glEnable(GL_TEXTURE_SHADER_NV); - checkGLcall("glEnable(GL_TEXTURE_SHADER_NV)"); - /* Set up the previous texture input for all shader units. This applies to bump mapping, and in d3d * the previous texture where to source the offset from is always unit - 1. */ diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 0a6bd2b7ba4..12ec046624d 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -2234,8 +2234,8 @@ err_out: IWineD3DStateBlock_Release((IWineD3DStateBlock *) This->stateBlock); This->stateBlock = NULL; } - This->shader_backend->shader_free_private(iface); This->frag_pipe->free_private(iface); + This->shader_backend->shader_free_private(iface); return hr; } @@ -2324,8 +2324,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D } /* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */ - This->shader_backend->shader_free_private(iface); This->frag_pipe->free_private(iface); + This->shader_backend->shader_free_private(iface); /* Release the buffers (with sanity checks)*/ TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget); @@ -6182,12 +6182,17 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONS TRACE("Surface %p is onscreen\n", surface); + ActivateContext(This, surface, CTXUSAGE_CLEAR); + ENTER_GL(); GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)); buffer = surface_get_gl_buffer(surface, swapchain); glDrawBuffer(buffer); checkGLcall("glDrawBuffer()"); } else { TRACE("Surface %p is offscreen\n", surface); + + ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_CLEAR); + ENTER_GL(); bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->dst_fbo); attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, 0, surface); GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0)); @@ -6206,7 +6211,6 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONS } else { glDisable(GL_SCISSOR_TEST); } - IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE)); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORWRITEENABLE)); @@ -6227,6 +6231,8 @@ static void color_fill_fbo(IWineD3DDevice *iface, IWineD3DSurface *surface, CONS glDrawBuffer(GL_BACK); checkGLcall("glDrawBuffer()"); } + + LEAVE_GL(); } static inline DWORD argb_to_fmt(DWORD color, WINED3DFORMAT destfmt) { @@ -6348,9 +6354,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD } if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) { - ENTER_GL(); color_fill_fbo(iface, pSurface, pRect, color); - LEAVE_GL(); return WINED3D_OK; } else { /* Just forward this to the DirectDraw blitting engine */ @@ -7248,8 +7252,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE This->depth_blt_rb_w = 0; This->depth_blt_rb_h = 0; } - This->shader_backend->shader_free_private(iface); This->frag_pipe->free_private(iface); + This->shader_backend->shader_free_private(iface); for (i = 0; i < GL_LIMITS(textures); i++) { /* Textures are recreated below */ diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index a95c7783e3d..9cbb40650ce 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -1963,6 +1963,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter /* Check if we support bumpmapping for a format */ static BOOL CheckBumpMapCapability(UINT Adapter, WINED3DFORMAT CheckFormat) { + /* TODO: Check this in the fixed function pipeline backend */ if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) { switch (CheckFormat) { case WINED3DFMT_V8U8: @@ -1984,6 +1985,20 @@ static BOOL CheckBumpMapCapability(UINT Adapter, WINED3DFORMAT CheckFormat) return FALSE; } } + if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { + switch (CheckFormat) { + case WINED3DFMT_V8U8: + case WINED3DFMT_V16U16: + case WINED3DFMT_L6V5U5: + case WINED3DFMT_X8L8V8U8: + case WINED3DFMT_Q8W8V8U8: + TRACE_(d3d_caps)("[OK]\n"); + return TRUE; + default: + TRACE_(d3d_caps)("[FAILED]\n"); + return FALSE; + } + } TRACE_(d3d_caps)("[FAILED]\n"); return FALSE; } @@ -2902,7 +2917,9 @@ static const struct fragment_pipeline *select_fragment_implementation(UINT Adapt int ps_selected_mode; select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode); - if(ps_selected_mode == SHADER_ATI) { + if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) { + return &arbfp_fragment_pipeline; + } else if(ps_selected_mode == SHADER_ATI) { return &atifs_fragment_pipeline; } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) { return &nvts_fragment_pipeline; diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index 9a47f8b9eb9..fd96ea25767 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -922,8 +922,6 @@ void drawPrimitive(IWineD3DDevice *iface, int minIndex) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DSwapChain *swapchain; - IWineD3DBaseTexture *texture = NULL; IWineD3DSurfaceImpl *target; int i; @@ -932,43 +930,9 @@ void drawPrimitive(IWineD3DDevice *iface, /* Invalidate the back buffer memory so LockRect will read it the next time */ for(i = 0; i < GL_LIMITS(buffers); i++) { target = (IWineD3DSurfaceImpl *) This->render_targets[i]; - - /* TODO: Only do all that if we're going to change anything - * Texture container dirtification does not work quite right yet - */ - if(target /*&& target->Flags & (SFLAG_INTEXTURE | SFLAG_INSYSMEM)*/) { - swapchain = NULL; - texture = NULL; - - if(i == 0) { - IWineD3DSurface_GetContainer((IWineD3DSurface *) target, &IID_IWineD3DSwapChain, (void **)&swapchain); - - /* Need the surface in the drawable! */ - IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL); - - /* TODO: Move fbo logic to ModifyLocation */ - IWineD3DSurface_ModifyLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, TRUE); - if(swapchain) { - /* Onscreen target. Invalidate system memory copy and texture copy */ - IWineD3DSwapChain_Release(swapchain); - } else if(wined3d_settings.offscreen_rendering_mode != ORM_FBO) { - /* Non-FBO target: Invalidate system copy, texture copy and dirtify the container */ - /* TODO: Move container dirtification to ModifyLocation */ - IWineD3DSurface_GetContainer((IWineD3DSurface *) target, &IID_IWineD3DBaseTexture, (void **)&texture); - - if(texture) { - IWineD3DBaseTexture_SetDirty(texture, TRUE); - IWineD3DTexture_Release(texture); - } - } else { - /* FBO offscreen target. Texture == Drawable */ - target->Flags |= SFLAG_INTEXTURE; - } - } else { - /* Must be an fbo render target */ - IWineD3DSurface_ModifyLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, TRUE); - target->Flags |= SFLAG_INTEXTURE; - } + if (target) { + IWineD3DSurface_LoadLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, NULL); + IWineD3DSurface_ModifyLocation((IWineD3DSurface *) target, SFLAG_INDRAWABLE, TRUE); } } diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index ce84ea75fb9..80c4411fbd8 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -3527,7 +3527,7 @@ static void shader_glsl_free(IWineD3DDevice *iface) { GL_EXTCALL(glDeleteObjectARB(priv->depth_blt_glsl_program_id)); } - hash_table_destroy(priv->glsl_program_lookup); + hash_table_destroy(priv->glsl_program_lookup, NULL, NULL); HeapFree(GetProcessHeap(), 0, This->shader_priv); This->shader_priv = NULL; diff --git a/dlls/wined3d/surface_base.c b/dlls/wined3d/surface_base.c index 57809e1e1a7..400c7a7bd13 100644 --- a/dlls/wined3d/surface_base.c +++ b/dlls/wined3d/surface_base.c @@ -850,42 +850,48 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, FIXME("Filters not supported in software blit\n"); } - if (Src == This) + /* First check for the validity of source / destination rectangles. This was + * verified using a test application + by MSDN. + */ + if ((Src != NULL) && (SrcRect != NULL) && + ((SrcRect->bottom > Src->currentDesc.Height)||(SrcRect->bottom < 0) || + (SrcRect->top > Src->currentDesc.Height)||(SrcRect->top < 0) || + (SrcRect->left > Src->currentDesc.Width) ||(SrcRect->left < 0) || + (SrcRect->right > Src->currentDesc.Width) ||(SrcRect->right < 0) || + (SrcRect->right < SrcRect->left) ||(SrcRect->bottom < SrcRect->top))) { - IWineD3DSurface_LockRect(iface, &dlock, NULL, 0); - dfmt = This->resource.format; - slock = dlock; - sfmt = dfmt; - sEntry = getFormatDescEntry(sfmt, NULL, NULL); - dEntry = sEntry; + WARN("Application gave us bad source rectangle for Blt.\n"); + return WINEDDERR_INVALIDRECT; } - else + /* For the Destination rect, it can be out of bounds on the condition that a clipper + * is set for the given surface. + */ + if ((/*This->clipper == NULL*/ TRUE) && (DestRect) && + ((DestRect->bottom > This->currentDesc.Height)||(DestRect->bottom < 0) || + (DestRect->top > This->currentDesc.Height)||(DestRect->top < 0) || + (DestRect->left > This->currentDesc.Width) ||(DestRect->left < 0) || + (DestRect->right > This->currentDesc.Width) ||(DestRect->right < 0) || + (DestRect->right < DestRect->left) ||(DestRect->bottom < DestRect->top))) { - dfmt = This->resource.format; - dEntry = getFormatDescEntry(dfmt, NULL, NULL); - if (Src) - { - if(This->resource.format != Src->resource.format) { - Src = surface_convert_format(Src, dfmt); - if(!Src) { - /* The conv function writes a FIXME */ - WARN("Cannot convert source surface format to dest format\n"); - goto release; - } - } - IWineD3DSurface_LockRect((IWineD3DSurface *) Src, &slock, NULL, WINED3DLOCK_READONLY); - sfmt = Src->resource.format; - } - sEntry = getFormatDescEntry(sfmt, NULL, NULL); - IWineD3DSurface_LockRect(iface, &dlock,NULL,0); + WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n"); + return WINEDDERR_INVALIDRECT; } - if (!DDBltFx || !(DDBltFx->dwDDFX)) Flags &= ~WINEDDBLT_DDFX; + /* Now handle negative values in the rectangles. Warning: only supported for now + in the 'simple' cases (ie not in any stretching / rotation cases). - if (sEntry->isFourcc && dEntry->isFourcc) + First, the case where nothing is to be done. + */ + if ((DestRect && ((DestRect->bottom <= 0) || (DestRect->right <= 0) || + (DestRect->top >= (int) This->currentDesc.Height) || + (DestRect->left >= (int) This->currentDesc.Width))) || + ((Src != NULL) && (SrcRect != NULL) && + ((SrcRect->bottom <= 0) || (SrcRect->right <= 0) || + (SrcRect->top >= (int) Src->currentDesc.Height) || + (SrcRect->left >= (int) Src->currentDesc.Width)) )) { - memcpy(dlock.pBits, slock.pBits, This->resource.size); - goto release; + TRACE("Nothing to be done !\n"); + return WINED3D_OK; } if (DestRect) @@ -919,54 +925,8 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, } } - /* First check for the validity of source / destination rectangles. This was - * verified using a test application + by MSDN. - */ - if ((Src != NULL) && - ((xsrc.bottom > Src->currentDesc.Height) || (xsrc.bottom < 0) || - (xsrc.top > Src->currentDesc.Height) || (xsrc.top < 0) || - (xsrc.left > Src->currentDesc.Width) || (xsrc.left < 0) || - (xsrc.right > Src->currentDesc.Width) || (xsrc.right < 0) || - (xsrc.right < xsrc.left) || (xsrc.bottom < xsrc.top))) - { - WARN("Application gave us bad source rectangle for Blt.\n"); - ret = WINEDDERR_INVALIDRECT; - goto release; - } - /* For the Destination rect, it can be out of bounds on the condition that a clipper - * is set for the given surface. - */ - if ((/*This->clipper == NULL*/ TRUE) && - ((xdst.bottom > This->currentDesc.Height) || (xdst.bottom < 0) || - (xdst.top > This->currentDesc.Height) || (xdst.top < 0) || - (xdst.left > This->currentDesc.Width) || (xdst.left < 0) || - (xdst.right > This->currentDesc.Width) || (xdst.right < 0) || - (xdst.right < xdst.left) || (xdst.bottom < xdst.top))) - { - WARN("Application gave us bad destination rectangle for Blt without a clipper set.\n"); - ret = WINEDDERR_INVALIDRECT; - goto release; - } - - /* Now handle negative values in the rectangles. Warning: only supported for now - in the 'simple' cases (ie not in any stretching / rotation cases). - - First, the case where nothing is to be done. - */ - if (((xdst.bottom <= 0) || (xdst.right <= 0) || - (xdst.top >= (int) This->currentDesc.Height) || - (xdst.left >= (int) This->currentDesc.Width)) || - ((Src != NULL) && - ((xsrc.bottom <= 0) || (xsrc.right <= 0) || - (xsrc.top >= (int) Src->currentDesc.Height) || - (xsrc.left >= (int) Src->currentDesc.Width)) )) - { - TRACE("Nothing to be done !\n"); - goto release; - } - /* The easy case : the source-less blits.... */ - if (Src == NULL) + if (Src == NULL && DestRect) { RECT full_rect; RECT temp_rect; /* No idea if intersect rect can be the same as one of the source rect */ @@ -975,44 +935,44 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, full_rect.top = 0; full_rect.right = This->currentDesc.Width; full_rect.bottom = This->currentDesc.Height; - IntersectRect(&temp_rect, &full_rect, &xdst); + IntersectRect(&temp_rect, &full_rect, DestRect); xdst = temp_rect; } - else + else if (DestRect) { /* Only handle clipping on the destination rectangle */ - int clip_horiz = (xdst.left < 0) || (xdst.right > (int) This->currentDesc.Width ); - int clip_vert = (xdst.top < 0) || (xdst.bottom > (int) This->currentDesc.Height); + int clip_horiz = (DestRect->left < 0) || (DestRect->right > (int) This->currentDesc.Width ); + int clip_vert = (DestRect->top < 0) || (DestRect->bottom > (int) This->currentDesc.Height); if (clip_vert || clip_horiz) { /* Now check if this is a special case or not... */ - if ((((xdst.bottom - xdst.top ) != (xsrc.bottom - xsrc.top )) && clip_vert ) || - (((xdst.right - xdst.left) != (xsrc.right - xsrc.left)) && clip_horiz) || + if ((((DestRect->bottom - DestRect->top ) != (xsrc.bottom - xsrc.top )) && clip_vert ) || + (((DestRect->right - DestRect->left) != (xsrc.right - xsrc.left)) && clip_horiz) || (Flags & WINEDDBLT_DDFX)) { WARN("Out of screen rectangle in special case. Not handled right now.\n"); - goto release; + return WINED3D_OK; } if (clip_horiz) { - if (xdst.left < 0) { xsrc.left -= xdst.left; xdst.left = 0; } - if (xdst.right > This->currentDesc.Width) + if (DestRect->left < 0) { xsrc.left -= DestRect->left; xdst.left = 0; } + if (DestRect->right > This->currentDesc.Width) { - xsrc.right -= (xdst.right - (int) This->currentDesc.Width); + xsrc.right -= (DestRect->right - (int) This->currentDesc.Width); xdst.right = (int) This->currentDesc.Width; } } if (clip_vert) { - if (xdst.top < 0) + if (DestRect->top < 0) { - xsrc.top -= xdst.top; + xsrc.top -= DestRect->top; xdst.top = 0; } - if (xdst.bottom > This->currentDesc.Height) + if (DestRect->bottom > This->currentDesc.Height) { - xsrc.bottom -= (xdst.bottom - (int) This->currentDesc.Height); + xsrc.bottom -= (DestRect->bottom - (int) This->currentDesc.Height); xdst.bottom = (int) This->currentDesc.Height; } } @@ -1025,8 +985,52 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, (xsrc.left >= (int) Src->currentDesc.Width)) { TRACE("Nothing to be done after clipping !\n"); - goto release; + return WINED3D_OK; + } + } + } + + if (Src == This) + { + IWineD3DSurface_LockRect(iface, &dlock, NULL, 0); + dfmt = This->resource.format; + slock = dlock; + sfmt = dfmt; + sEntry = getFormatDescEntry(sfmt, NULL, NULL); + dEntry = sEntry; + } + else + { + dfmt = This->resource.format; + dEntry = getFormatDescEntry(dfmt, NULL, NULL); + if (Src) + { + if(This->resource.format != Src->resource.format) { + Src = surface_convert_format(Src, dfmt); + if(!Src) { + /* The conv function writes a FIXME */ + WARN("Cannot convert source surface format to dest format\n"); + goto release; + } } + IWineD3DSurface_LockRect((IWineD3DSurface *) Src, &slock, NULL, WINED3DLOCK_READONLY); + sfmt = Src->resource.format; + } + sEntry = getFormatDescEntry(sfmt, NULL, NULL); + if (DestRect) + IWineD3DSurface_LockRect(iface, &dlock, &xdst, 0); + else + IWineD3DSurface_LockRect(iface, &dlock, NULL, 0); + } + + if (!DDBltFx || !(DDBltFx->dwDDFX)) Flags &= ~WINEDDBLT_DDFX; + + if (sEntry->isFourcc && dEntry->isFourcc) + { + if (!DestRect || Src == This) + { + memcpy(dlock.pBits, slock.pBits, This->resource.size); + goto release; } } @@ -1039,7 +1043,10 @@ IWineD3DBaseSurfaceImpl_Blt(IWineD3DSurface *iface, assert(width <= dlock.Pitch); - dbuf = (BYTE*)dlock.pBits+(xdst.top*dlock.Pitch)+(xdst.left*bpp); + if (DestRect && Src != This) + dbuf = (BYTE*)dlock.pBits; + else + dbuf = (BYTE*)dlock.pBits+(xdst.top*dlock.Pitch)+(xdst.left*bpp); if (Flags & WINEDDBLT_WAIT) { diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index da08d4f0ece..a9fc7807903 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -1576,12 +1576,15 @@ hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function return table; } -void hash_table_destroy(hash_table_t *table) +void hash_table_destroy(hash_table_t *table, void (*free_value)(void *value, void *cb), void *cb) { unsigned int i = 0; for (i = 0; i < table->entry_count; ++i) { + if(free_value) { + free_value(table->entries[i].value, cb); + } HeapFree(GetProcessHeap(), 0, table->entries[i].key); } @@ -1750,7 +1753,7 @@ void *hash_table_get(hash_table_t *table, void *key) } #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info -void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct texture_stage_op op[MAX_TEXTURES]) { +void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct ffp_settings *settings, BOOL ignore_textype) { #define ARG1 0x01 #define ARG2 0x02 #define ARG0 0x04 @@ -1785,47 +1788,71 @@ void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct texture_stage_op op[M }; unsigned int i; DWORD ttff; + DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2; for(i = 0; i < GL_LIMITS(texture_stages); i++) { IWineD3DBaseTextureImpl *texture; if(stateblock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) { - op[i].cop = WINED3DTOP_DISABLE; - op[i].aop = WINED3DTOP_DISABLE; - op[i].carg0 = op[i].carg1 = op[i].carg2 = 0xffffffff; - op[i].aarg0 = op[i].aarg1 = op[i].aarg2 = 0xffffffff; - op[i].color_correction = WINED3DFMT_UNKNOWN; - op[i].dst = 0xffffffff; + settings->op[i].cop = WINED3DTOP_DISABLE; + settings->op[i].aop = WINED3DTOP_DISABLE; + /* 0x3F: set all 6 bits of the args to 1 */ + settings->op[i].carg0 = settings->op[i].carg1 = settings->op[i].carg2 = 0x3F; + settings->op[i].aarg0 = settings->op[i].aarg1 = settings->op[i].aarg2 = 0x3F; + settings->op[i].color_correction = WINED3DFMT_UNKNOWN; + settings->op[i].dst = resultreg; i++; break; } texture = (IWineD3DBaseTextureImpl *) stateblock->textures[i]; - op[i].color_correction = texture ? texture->baseTexture.shader_conversion_group : WINED3DFMT_UNKNOWN; + if(texture) { + settings->op[i].color_correction = texture->baseTexture.shader_conversion_group; + if(ignore_textype) { + settings->op[i].tex_type = tex_1d; + } else { + switch(stateblock->textureDimensions[i]) { + case GL_TEXTURE_1D: + settings->op[i].tex_type = tex_1d; + break; + case GL_TEXTURE_2D: + settings->op[i].tex_type = tex_2d; + break; + case GL_TEXTURE_3D: + settings->op[i].tex_type = tex_3d; + break; + case GL_TEXTURE_CUBE_MAP_ARB: + settings->op[i].tex_type = tex_cube; + break; + case GL_TEXTURE_RECTANGLE_ARB: + settings->op[i].tex_type = tex_rect; + break; + } + } + } else { + settings->op[i].color_correction = WINED3DFMT_UNKNOWN; + settings->op[i].tex_type = tex_1d; + } - op[i].cop = stateblock->textureState[i][WINED3DTSS_COLOROP]; - op[i].aop = stateblock->textureState[i][WINED3DTSS_ALPHAOP]; + cop = stateblock->textureState[i][WINED3DTSS_COLOROP]; + aop = stateblock->textureState[i][WINED3DTSS_ALPHAOP]; - op[i].carg1 = (args[op[i].cop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_COLORARG1] : 0xffffffff; - op[i].carg2 = (args[op[i].cop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_COLORARG2] : 0xffffffff; - op[i].carg0 = (args[op[i].cop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_COLORARG0] : 0xffffffff; + carg1 = (args[cop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_COLORARG1] : 0xffffffff; + carg2 = (args[cop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_COLORARG2] : 0xffffffff; + carg0 = (args[cop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_COLORARG0] : 0xffffffff; - if(is_invalid_op(stateblock->wineD3DDevice, i, op[i].cop, op[i].carg1, op[i].carg2, op[i].carg0)) { - op[i].carg0 = 0xffffffff; - op[i].carg2 = 0xffffffff; - op[i].carg1 = WINED3DTA_CURRENT; - op[i].cop = WINED3DTOP_SELECTARG1; + if(is_invalid_op(stateblock->wineD3DDevice, i, cop, + carg1, carg2, carg0)) { + carg0 = 0xffffffff; + carg2 = 0xffffffff; + carg1 = WINED3DTA_CURRENT; + cop = WINED3DTOP_SELECTARG1; } - op[i].aarg1 = (args[op[i].aop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG1] : 0xffffffff; - op[i].aarg2 = (args[op[i].aop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG2] : 0xffffffff; - op[i].aarg0 = (args[op[i].aop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG0] : 0xffffffff; + aarg1 = (args[aop] & ARG1) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG1] : 0xffffffff; + aarg2 = (args[aop] & ARG2) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG2] : 0xffffffff; + aarg0 = (args[aop] & ARG0) ? stateblock->textureState[i][WINED3DTSS_ALPHAARG0] : 0xffffffff; - if(is_invalid_op(stateblock->wineD3DDevice, i, op[i].aop, op[i].aarg1, op[i].aarg2, op[i].aarg0)) { - op[i].aarg0 = 0xffffffff; - op[i].aarg2 = 0xffffffff; - op[i].aarg1 = WINED3DTA_CURRENT; - op[i].aop = WINED3DTOP_SELECTARG1; - } else if(i == 0 && stateblock->textures[0] && + if(i == 0 && stateblock->textures[0] && stateblock->renderState[WINED3DRS_COLORKEYENABLE] && (stateblock->textureDimensions[0] == GL_TEXTURE_2D || stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) { @@ -1834,71 +1861,113 @@ void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct texture_stage_op op[M if(surf->CKeyFlags & WINEDDSD_CKSRCBLT && getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) { - if(op[0].aop == WINED3DTOP_DISABLE) { - op[0].aarg1 = WINED3DTA_TEXTURE; - op[0].aop = WINED3DTOP_SELECTARG1; + if(aop == WINED3DTOP_DISABLE) { + aarg1 = WINED3DTA_TEXTURE; + aop = WINED3DTOP_SELECTARG1; } - else if(op[0].aop == WINED3DTOP_SELECTARG1 && op[0].aarg1 != WINED3DTA_TEXTURE) { + else if(aop == WINED3DTOP_SELECTARG1 && aarg1 != WINED3DTA_TEXTURE) { if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) { - op[0].aarg2 = WINED3DTA_TEXTURE; - op[0].aop = WINED3DTOP_MODULATE; + aarg2 = WINED3DTA_TEXTURE; + aop = WINED3DTOP_MODULATE; } - else op[0].aarg1 = WINED3DTA_TEXTURE; + else aarg1 = WINED3DTA_TEXTURE; } - else if(op[0].aop == WINED3DTOP_SELECTARG2 && op[0].aarg2 != WINED3DTA_TEXTURE) { + else if(aop == WINED3DTOP_SELECTARG2 && aarg2 != WINED3DTA_TEXTURE) { if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) { - op[0].aarg1 = WINED3DTA_TEXTURE; - op[0].aop = WINED3DTOP_MODULATE; + aarg1 = WINED3DTA_TEXTURE; + aop = WINED3DTOP_MODULATE; } - else op[0].aarg2 = WINED3DTA_TEXTURE; + else aarg2 = WINED3DTA_TEXTURE; } } } - if(op[i].carg1 == WINED3DTA_TEXTURE || op[i].carg2 == WINED3DTA_TEXTURE || op[i].carg0 == WINED3DTA_TEXTURE || - op[i].aarg1 == WINED3DTA_TEXTURE || op[i].aarg2 == WINED3DTA_TEXTURE || op[i].aarg0 == WINED3DTA_TEXTURE) { + if(is_invalid_op(stateblock->wineD3DDevice, i, aop, + aarg1, aarg2, aarg0)) { + aarg0 = 0xffffffff; + aarg2 = 0xffffffff; + aarg1 = WINED3DTA_CURRENT; + aop = WINED3DTOP_SELECTARG1; + } + + if(carg1 == WINED3DTA_TEXTURE || carg2 == WINED3DTA_TEXTURE || carg0 == WINED3DTA_TEXTURE || + aarg1 == WINED3DTA_TEXTURE || aarg2 == WINED3DTA_TEXTURE || aarg0 == WINED3DTA_TEXTURE) { ttff = stateblock->textureState[i][WINED3DTSS_TEXTURETRANSFORMFLAGS]; if(ttff == (WINED3DTTFF_PROJECTED | WINED3DTTFF_COUNT3)) { - op[i].projected = proj_count3; + settings->op[i].projected = proj_count3; } else if(ttff == (WINED3DTTFF_PROJECTED | WINED3DTTFF_COUNT4)) { - op[i].projected = proj_count4; + settings->op[i].projected = proj_count4; } else { - op[i].projected = proj_none; + settings->op[i].projected = proj_none; } } else { - op[i].projected = proj_none; + settings->op[i].projected = proj_none; } - op[i].dst = stateblock->textureState[i][WINED3DTSS_RESULTARG]; + settings->op[i].cop = cop; + settings->op[i].aop = aop; + settings->op[i].carg0 = carg0; + settings->op[i].carg1 = carg1; + settings->op[i].carg2 = carg2; + settings->op[i].aarg0 = aarg0; + settings->op[i].aarg1 = aarg1; + settings->op[i].aarg2 = aarg2; + + if(stateblock->textureState[i][WINED3DTSS_RESULTARG] == WINED3DTA_TEMP) { + settings->op[i].dst = tempreg; + } else { + settings->op[i].dst = resultreg; + } } /* Clear unsupported stages */ for(; i < MAX_TEXTURES; i++) { - memset(&op[i], 0xff, sizeof(op[i])); + memset(&settings->op[i], 0xff, sizeof(settings->op[i])); + } + + if(stateblock->renderState[WINED3DRS_FOGENABLE] == FALSE) { + settings->fog = FOG_OFF; + } else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) { + switch(stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) { + case WINED3DFOG_NONE: + case WINED3DFOG_LINEAR: + settings->fog = FOG_LINEAR; + break; + case WINED3DFOG_EXP: + settings->fog = FOG_EXP; + break; + case WINED3DFOG_EXP2: + settings->fog = FOG_EXP2; + break; + } + } else { + switch(stateblock->renderState[WINED3DRS_FOGTABLEMODE]) { + case WINED3DFOG_LINEAR: + settings->fog = FOG_LINEAR; + break; + case WINED3DFOG_EXP: + settings->fog = FOG_EXP; + break; + case WINED3DFOG_EXP2: + settings->fog = FOG_EXP2; + break; + } } } #undef GLINFO_LOCATION -struct ffp_desc *find_ffp_shader(struct list *shaders, struct texture_stage_op op[MAX_TEXTURES]) +struct ffp_desc *find_ffp_shader(hash_table_t *fragment_shaders, struct ffp_settings *settings) { - struct ffp_desc *entry; + return (struct ffp_desc *)hash_table_get(fragment_shaders, settings);} - /* TODO: Optimize this. Finding the shader can be optimized by e.g. sorting the list, - * or maybe consider using hashtables +void add_ffp_shader(hash_table_t *shaders, struct ffp_desc *desc) { + struct ffp_settings *key = HeapAlloc(GetProcessHeap(), 0, sizeof(*key)); + /* Note that the key is the implementation independent part of the ffp_desc structure, + * whereas desc points to an extended structure with implementation specific parts. + * Make a copy of the key because hash_table_put takes ownership of it */ - LIST_FOR_EACH_ENTRY(entry, shaders, struct ffp_desc, entry) { - if(memcmp(op, entry->op, sizeof(struct texture_stage_op) * MAX_TEXTURES) == 0) { - TRACE("Found shader entry %p\n", entry); - return entry; - } - } - - TRACE("Shader not found\n"); - return NULL; -} - -void add_ffp_shader(struct list *shaders, struct ffp_desc *desc) { - list_add_head(shaders, &desc->entry); + *key = desc->settings; + hash_table_put(shaders, key, desc); } /* Activates the texture dimension according to the bound D3D texture. @@ -1995,3 +2064,36 @@ void sampler_texdim(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont texture_activate_dimensions(sampler, stateblock, context); } #undef GLINFO_LOCATION + +unsigned int ffp_program_key_hash(void *key) { + struct ffp_settings *k = (struct ffp_settings *)key; + unsigned int hash = 0, i; + DWORD *blob; + + /* This takes the texture op settings of stage 0 and 1 into account. + * how exactly depends on the memory laybout of the compiler, but it + * should not matter too much. Stages > 1 are used rarely, so there's + * no need to process them. Even if they're used it is likely that + * the ffp setup has distinct stage 0 and 1 settings. + */ + for(i = 0; i < 2; i++) { + blob = (DWORD *) &k->op[i]; + hash ^= blob[0] ^ blob[1]; + } + + hash += ~(hash << 15); + hash ^= (hash >> 10); + hash += (hash << 3); + hash ^= (hash >> 6); + hash += ~(hash << 11); + hash ^= (hash >> 16); + + return hash; +} + +BOOL ffp_program_key_compare(void *keya, void *keyb) { + struct ffp_settings *ka = (struct ffp_settings *)keya; + struct ffp_settings *kb = (struct ffp_settings *)keyb; + + return memcmp(ka, kb, sizeof(*ka)) == 0; +} diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 61b29839c07..7ba66177f52 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -68,7 +68,7 @@ typedef struct { } hash_table_t; hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function_t *compare_function); -void hash_table_destroy(hash_table_t *table); +void hash_table_destroy(hash_table_t *table, void (*free_value)(void *value, void *cb), void *cb); void *hash_table_get(hash_table_t *table, void *key); void hash_table_put(hash_table_t *table, void *key, void *value); void hash_table_remove(hash_table_t *table, void *key); @@ -267,6 +267,8 @@ struct shader_arb_priv { GLuint current_fprogram_id; GLuint depth_blt_vprogram_id; GLuint depth_blt_fprogram_id; + BOOL use_arbfp_fixed_func; + hash_table_t *fragment_shaders; }; /* X11 locking */ @@ -561,6 +563,7 @@ extern const struct StateEntryTemplate misc_state_template[]; extern const struct StateEntryTemplate ffp_vertexstate_template[]; extern const struct fragment_pipeline ffp_fragment_pipeline; extern const struct fragment_pipeline atifs_fragment_pipeline; +extern const struct fragment_pipeline arbfp_fragment_pipeline; extern const struct fragment_pipeline nvts_fragment_pipeline; extern const struct fragment_pipeline nvrc_fragment_pipeline; @@ -714,9 +717,24 @@ HRESULT tesselate_rectpatch(IWineD3DDeviceImpl *This, struct WineD3DRectPatch *p enum projection_types { - proj_none, - proj_count3, - proj_count4 + proj_none = 0, + proj_count3 = 1, + proj_count4 = 2 +}; + +enum tex_types +{ + tex_1d = 0, + tex_2d = 1, + tex_3d = 2, + tex_cube = 3, + tex_rect = 4 +}; + +enum dst_arg +{ + resultreg = 0, + tempreg = 1 }; /***************************************************************************** @@ -724,23 +742,35 @@ enum projection_types */ struct texture_stage_op { - WINED3DTEXTUREOP cop, aop; - DWORD carg1, carg2, carg0; - DWORD aarg1, aarg2, aarg0; + unsigned cop : 5, aop : 5; + unsigned carg1 : 6, carg2 : 6, carg0 : 6; + unsigned tex_type : 3; + unsigned dst : 1; + unsigned aarg1 : 6, aarg2 : 6, aarg0 : 6; + unsigned projected : 2; WINED3DFORMAT color_correction; - DWORD dst; - enum projection_types projected; +}; + +struct ffp_settings { + struct texture_stage_op op[MAX_TEXTURES]; + enum { + FOG_OFF, + FOG_LINEAR, + FOG_EXP, + FOG_EXP2 + } fog; }; struct ffp_desc { - struct texture_stage_op op[MAX_TEXTURES]; - struct list entry; + struct ffp_settings settings; }; -void gen_ffp_op(IWineD3DStateBlockImpl *stateblock,struct texture_stage_op op[MAX_TEXTURES]); -struct ffp_desc *find_ffp_shader(struct list *shaders, struct texture_stage_op op[MAX_TEXTURES]); -void add_ffp_shader(struct list *shaders, struct ffp_desc *desc); +void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct ffp_settings *settings, BOOL ignore_textype); +struct ffp_desc *find_ffp_shader(hash_table_t *fragment_shaders, struct ffp_settings *settings); +void add_ffp_shader(hash_table_t *shaders, struct ffp_desc *desc); +BOOL ffp_program_key_compare(void *keya, void *keyb); +unsigned int ffp_program_key_hash(void *key); /***************************************************************************** * IWineD3D implementation structure diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index accd6b4cbfd..e431786a985 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -763,6 +763,36 @@ static void X11DRV_MapNotify( HWND hwnd, XEvent *event ) /*********************************************************************** + * is_net_wm_state_maximized + */ +static BOOL is_net_wm_state_maximized( Display *display, struct x11drv_win_data *data ) +{ + Atom type, *state; + int format, ret = 0; + unsigned long i, count, remaining; + + wine_tsx11_lock(); + if (!XGetWindowProperty( display, data->whole_window, x11drv_atom(_NET_WM_STATE), 0, + 65536/sizeof(CARD32), False, XA_ATOM, &type, &format, &count, + &remaining, (unsigned char **)&state )) + { + if (type == XA_ATOM && format == 32) + { + for (i = 0; i < count; i++) + { + if (state[i] == x11drv_atom(_NET_WM_STATE_MAXIMIZED_VERT) || + state[i] == x11drv_atom(_NET_WM_STATE_MAXIMIZED_HORZ)) + ret++; + } + } + XFree( state ); + } + wine_tsx11_unlock(); + return (ret == 2); +} + + +/*********************************************************************** * X11DRV_ConfigureNotify */ void X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) @@ -792,8 +822,8 @@ void X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) rect.right = x + event->width; rect.bottom = y + event->height; OffsetRect( &rect, virtual_screen_rect.left, virtual_screen_rect.top ); - TRACE( "win %p new X rect %d,%d,%dx%d (event %d,%d,%dx%d)\n", - hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, + TRACE( "win %p/%lx new X rect %d,%d,%dx%d (event %d,%d,%dx%d)\n", + hwnd, data->whole_window, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, event->x, event->y, event->width, event->height ); X11DRV_X_to_window_rect( data, &rect ); @@ -803,6 +833,25 @@ void X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev ) cy = rect.bottom - rect.top; flags = SWP_NOACTIVATE | SWP_NOZORDER; + if (is_net_wm_state_maximized( event->display, data )) + { + if (!IsZoomed( data->hwnd )) + { + TRACE( "win %p/%lx is maximized\n", data->hwnd, data->whole_window ); + SendMessageW( data->hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0 ); + return; + } + } + else + { + if (IsZoomed( data->hwnd )) + { + TRACE( "window %p/%lx is no longer maximized\n", data->hwnd, data->whole_window ); + SendMessageW( data->hwnd, WM_SYSCOMMAND, SC_RESTORE, 0 ); + return; + } + } + /* Compare what has changed */ GetWindowRect( hwnd, &rect ); @@ -883,40 +932,23 @@ static void handle_wm_state_notify( struct x11drv_win_data *data, XPropertyEvent if (data->iconic && data->wm_state == NormalState) /* restore window */ { - int x, y; - unsigned int width, height, border, depth; - Window root, top; - WINDOWPLACEMENT wp; - RECT rect; - - /* FIXME: hack */ - wine_tsx11_lock(); - XGetGeometry( event->display, data->whole_window, &root, &x, &y, &width, &height, - &border, &depth ); - XTranslateCoordinates( event->display, data->whole_window, root, 0, 0, &x, &y, &top ); - wine_tsx11_unlock(); - rect.left = x; - rect.top = y; - rect.right = x + width; - rect.bottom = y + height; - OffsetRect( &rect, virtual_screen_rect.left, virtual_screen_rect.top ); - X11DRV_X_to_window_rect( data, &rect ); - - wp.length = sizeof(wp); - GetWindowPlacement( data->hwnd, &wp ); - wp.flags = 0; - wp.showCmd = SW_RESTORE; - wp.rcNormalPosition = rect; - - TRACE( "restoring win %p/%lx\n", data->hwnd, data->whole_window ); data->iconic = FALSE; - SetWindowPlacement( data->hwnd, &wp ); + if (is_net_wm_state_maximized( event->display, data )) + { + TRACE( "restoring to max %p/%lx\n", data->hwnd, data->whole_window ); + SendMessageW( data->hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0 ); + } + else + { + TRACE( "restoring win %p/%lx\n", data->hwnd, data->whole_window ); + SendMessageW( data->hwnd, WM_SYSCOMMAND, SC_RESTORE, 0 ); + } } else if (!data->iconic && data->wm_state == IconicState) { TRACE( "minimizing win %p/%lx\n", data->hwnd, data->whole_window ); data->iconic = TRUE; - ShowWindow( data->hwnd, SW_MINIMIZE ); + SendMessageW( data->hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0 ); } } diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index e177948e0ef..8c1ca0de193 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2072,6 +2072,48 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, } +/*********************************************************************** + * ShowWindow (X11DRV.@) + */ +UINT X11DRV_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) +{ + int x, y; + unsigned int width, height, border, depth; + Window root, top; + DWORD style = GetWindowLongW( hwnd, GWL_STYLE ); + struct x11drv_thread_data *thread_data = x11drv_thread_data(); + struct x11drv_win_data *data = X11DRV_get_win_data( hwnd ); + + if (!data || !data->whole_window || !data->managed || !data->mapped || data->iconic) return swp; + if (style & WS_MINIMIZE) return swp; + + /* only fetch the new rectangle if the ShowWindow was a result of a window manager event */ + + if (!thread_data->current_event || thread_data->current_event->xany.window != data->whole_window) + return swp; + + if (thread_data->current_event->type != ConfigureNotify && + thread_data->current_event->type != PropertyNotify) + return swp; + + TRACE( "win %p/%lx cmd %d at %s flags %08x\n", + hwnd, data->whole_window, cmd, wine_dbgstr_rect(rect), swp ); + + wine_tsx11_lock(); + XGetGeometry( thread_data->display, data->whole_window, + &root, &x, &y, &width, &height, &border, &depth ); + XTranslateCoordinates( thread_data->display, data->whole_window, root, 0, 0, &x, &y, &top ); + wine_tsx11_unlock(); + rect->left = x; + rect->top = y; + rect->right = x + width; + rect->bottom = y + height; + OffsetRect( rect, virtual_screen_rect.left, virtual_screen_rect.top ); + X11DRV_X_to_window_rect( data, rect ); + return swp & ~(SWP_NOMOVE | SWP_NOCLIENTMOVE | SWP_NOSIZE | SWP_NOCLIENTSIZE); +} + + /********************************************************************** * SetWindowIcon (X11DRV.@) * diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index 459ea9e6bdc..cacc5b9b4b0 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -111,7 +111,8 @@ @ cdecl SetWindowRgn(long long long) X11DRV_SetWindowRgn @ cdecl SetWindowStyle(ptr long) X11DRV_SetWindowStyle @ cdecl SetWindowText(long wstr) X11DRV_SetWindowText -@ cdecl SysCommand(long long) X11DRV_SysCommand +@ cdecl ShowWindow(long long ptr long) X11DRV_ShowWindow +@ cdecl SysCommand(long long long) X11DRV_SysCommand @ cdecl WindowMessage(long long long long) X11DRV_WindowMessage @ cdecl WindowPosChanging(long long long ptr ptr ptr) X11DRV_WindowPosChanging @ cdecl WindowPosChanged(long long long ptr ptr ptr ptr) X11DRV_WindowPosChanged @@ -163,5 +164,5 @@ @ stdcall ImeSetCompositionString(long long ptr long ptr long) @ stdcall ImeConversionList(long wstr ptr long long) @ stdcall ImeProcessKey(long long long ptr) -@ stdcall ImeGetRegisterWordStyle(wstr long wstr) +@ stdcall ImeGetRegisterWordStyle(long ptr) @ stdcall ImeGetImeMenuItems(long long long ptr ptr long) diff --git a/dlls/winhttp/main.c b/dlls/winhttp/main.c index 28eb1201e1e..18059ba45ea 100644 --- a/dlls/winhttp/main.c +++ b/dlls/winhttp/main.c @@ -247,3 +247,15 @@ BOOL WINAPI WinHttpCloseHandle (HINTERNET hInternet) SetLastError(ERROR_NOT_SUPPORTED); return FALSE; } + +/*********************************************************************** + * WinHttpWriteData (winhttp.@) + */ +BOOL WINAPI WinHttpWriteData (HINTERNET hRequest, LPCVOID lpBuffer, + DWORD dwNumberOfBytesToWrite, LPDWORD lpdwNumberOfBytesWritten) +{ + FIXME("(%p, %d, %p): stub\n", lpBuffer, dwNumberOfBytesToWrite, lpdwNumberOfBytesWritten); + + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; +} diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index d417a564087..3b43550104d 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -74,7 +74,80 @@ static void test_OpenRequest (void) } +static void test_SendRequest (void) +{ + HINTERNET session, request, connection; + DWORD header_len, optional_len, total_len; + DWORD bytes_rw; + BOOL ret; + CHAR buffer[256]; + int i; + + static const WCHAR test_site[] = {'c','r','o','s','s','o','v','e','r','.', + 'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0}; + static const WCHAR content_type[] = + {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n', + '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0}; + static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0}; + static const WCHAR test_verb[] = {'P','O','S','T',0}; + static CHAR post_data[] = "mode=Test"; + static CHAR test_post[] = "mode => Test\\0\n"; + + header_len = -1L; + total_len = optional_len = sizeof(post_data); + memset(buffer, 0xff, sizeof(buffer)); + + session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, + WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); + todo_wine ok(session != NULL, "WinHttpOpen failed to open session.\n"); + + connection = WinHttpConnect (session, test_site, INTERNET_DEFAULT_HTTP_PORT, 0); + todo_wine ok(connection != NULL, + "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError()); + + request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE); + if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED) + { + skip("Network unreachable, skipping.\n"); + goto done; + } + todo_wine ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError()); + + ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, 0); + todo_wine ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError()); + + for (i = 3; post_data[i]; i++) + { + bytes_rw = -1; + ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw); + todo_wine ok(ret == TRUE, "WinHttpWriteData failed: %u.\n", GetLastError()); + todo_wine ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw); + } + + ret = WinHttpReceiveResponse(request, NULL); + todo_wine ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError()); + + bytes_rw = -1; + ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw); + todo_wine ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError()); + + todo_wine ok(bytes_rw == strlen(test_post), "Read %u bytes instead of %d.\n", + bytes_rw, strlen(test_post)); + todo_wine ok(strncmp(buffer, test_post, bytes_rw) == 0, + "Data read did not match, got '%s'.\n", buffer); + + ret = WinHttpCloseHandle(request); + todo_wine ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret); + done: + ret = WinHttpCloseHandle(connection); + todo_wine ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret); + ret = WinHttpCloseHandle(session); + todo_wine ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret); +} + START_TEST (winhttp) { test_OpenRequest(); + test_SendRequest(); } diff --git a/dlls/winhttp/winhttp.spec b/dlls/winhttp/winhttp.spec index 1017c71397f..c6ada031fe0 100644 --- a/dlls/winhttp/winhttp.spec +++ b/dlls/winhttp/winhttp.spec @@ -28,4 +28,4 @@ @ stub WinHttpSetTimeouts @ stub WinHttpTimeFromSystemTime @ stub WinHttpTimeToSystemTime -@ stub WinHttpWriteData +@ stdcall WinHttpWriteData(ptr ptr long ptr) diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index 2a786708e29..ba82a84b46a 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -2195,15 +2195,16 @@ static BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLev else headers = lpwhr->lpszRawHeaders; - len = (strlenW(headers) + 1) * sizeof(WCHAR); - if (len > *lpdwBufferLength) + len = strlenW(headers) * sizeof(WCHAR); + if (len + sizeof(WCHAR) > *lpdwBufferLength) { + len += sizeof(WCHAR); INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER); ret = FALSE; } else if (lpBuffer) { - memcpy(lpBuffer, headers, len); + memcpy(lpBuffer, headers, len + sizeof(WCHAR)); TRACE("returning data: %s\n", debugstr_wn(lpBuffer, len / sizeof(WCHAR))); ret = TRUE; } diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c index 8209b2243ca..0c4483b0c47 100644 --- a/dlls/wininet/tests/http.c +++ b/dlls/wininet/tests/http.c @@ -1072,7 +1072,9 @@ static void HttpHeaders_test(void) HINTERNET hConnect; HINTERNET hRequest; CHAR buffer[256]; + WCHAR wbuffer[256]; DWORD len = 256; + DWORD oldlen; DWORD index = 0; hSession = InternetOpen("Wine Regression Test", @@ -1150,19 +1152,47 @@ static void HttpHeaders_test(void) ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError()); ok(len > 40, "Invalid length (exp. more than 40, got %d)\n", len); ok(index == 0, "Index was incremented\n"); + oldlen = len; /* bytes; at least long enough to hold buffer & nul */ /* a working query */ index = 0; len = sizeof(buffer); + memset(buffer, 'x', sizeof(buffer)); ok(HttpQueryInfo(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n"); + ok(len + sizeof(CHAR) <= oldlen, "Result longer than advertised\n"); + ok((len < sizeof(buffer)-sizeof(CHAR)) && (buffer[len/sizeof(CHAR)] == 0),"No NUL at end\n"); + ok(len == strlen(buffer) * sizeof(CHAR), "Length wrong\n"); /* what's in the middle differs between Wine and Windows so currently we check only the beginning and the end */ ok(strncmp(buffer, "POST /posttest.php HTTP/1", 25)==0, "Invalid beginning of headers string\n"); ok(strcmp(buffer + strlen(buffer) - 4, "\r\n\r\n")==0, "Invalid end of headers string\n"); ok(index == 0, "Index was incremented\n"); + /* Like above two tests, but for W version */ + index = 0; + len = 0; + SetLastError(0xdeadbeef); + ok(HttpQueryInfoW(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS, + NULL,&len,&index) == FALSE,"Query worked\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError()); + ok(len > 80, "Invalid length (exp. more than 80, got %d)\n", len); + ok(index == 0, "Index was incremented\n"); + oldlen = len; /* bytes; at least long enough to hold buffer & nul */ + + /* a working query */ + index = 0; + len = sizeof(wbuffer); + memset(wbuffer, 'x', sizeof(wbuffer)); + ok(HttpQueryInfoW(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS, + wbuffer,&len,&index),"Unable to query header\n"); + ok(len + sizeof(WCHAR) <= oldlen, "Result longer than advertised\n"); + ok(len == lstrlenW(wbuffer) * sizeof(WCHAR), "Length wrong\n"); + ok((len < sizeof(wbuffer)-sizeof(WCHAR)) && (wbuffer[len/sizeof(WCHAR)] == 0),"No NUL at end\n"); + ok(index == 0, "Index was incremented\n"); + + /* end of W version tests */ ok(HttpAddRequestHeaders(hRequest,"Warning:test2",-1,HTTP_ADDREQ_FLAG_ADD), "Failed to add duplicate header using HTTP_ADDREQ_FLAG_ADD\n"); diff --git a/dlls/wininet/urlcache.c b/dlls/wininet/urlcache.c index 6e768933a07..1cfa8de7ca8 100644 --- a/dlls/wininet/urlcache.c +++ b/dlls/wininet/urlcache.c @@ -2339,7 +2339,7 @@ static BOOL WINAPI CommitUrlCacheEntryInternal( /* skip container path prefix */ lpszLocalFileName += lstrlenW(pContainer->path); - WideCharToMultiByte(CP_ACP, 0, lpszLocalFileName, -1, achFile, -1, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, lpszLocalFileName, -1, achFile, MAX_PATH, NULL, NULL); pchLocalFileName = achFile; for (cDirectory = 0; cDirectory < pHeader->DirectoryCount; cDirectory++) @@ -3107,6 +3107,9 @@ BOOL WINAPI FindNextUrlCacheEntryA( return FALSE; } +/*********************************************************************** + * FindNextUrlCacheEntryW (WININET.@) + */ BOOL WINAPI FindNextUrlCacheEntryW( HANDLE hEnumHandle, LPINTERNET_CACHE_ENTRY_INFOW lpNextCacheEntryInfo, diff --git a/include/Makefile.in b/include/Makefile.in index 99b06d90fae..882d89da625 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -350,6 +350,7 @@ SRCDIR_INCLUDES = \ pshpack4.h \ pshpack8.h \ ras.h \ + raserror.h \ reason.h \ regstr.h \ richedit.h \ diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 931a1307596..e2340dde583 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -125,11 +125,66 @@ typedef struct _WAIT_CONTEXT_BLOCK { PKDPC BufferChainingDpc; } WAIT_CONTEXT_BLOCK, *PWAIT_CONTEXT_BLOCK; +#define DO_BUFFERED_IO 0x00000004 +#define DO_EXCLUSIVE 0x00000008 +#define DO_DIRECT_IO 0x00000010 +#define DO_MAP_IO_BUFFER 0x00000020 +#define DO_DEVICE_INITIALIZING 0x00000080 +#define DO_SHUTDOWN_REGISTERED 0x00000800 +#define DO_BUS_ENUMERATED_DEVICE 0x00001000 +#define DO_POWER_PAGABLE 0x00002000 +#define DO_POWER_INRUSH 0x00004000 + +#define IO_NO_INCREMENT 0 +#define IO_CD_ROM_INCREMENT 1 +#define IO_DISK_INCREMENT 1 +#define IO_KEYBOARD_INCREMENT 6 +#define IO_MAILSLOT_INCREMENT 2 +#define IO_MOUSE_INCREMENT 6 +#define IO_NAMED_PIPE_INCREMENT 2 +#define IO_NETWORK_INCREMENT 2 +#define IO_PARALLEL_INCREMENT 1 +#define IO_SERIAL_INCREMENT 2 +#define IO_SOUND_INCREMENT 8 +#define IO_VIDEO_INCREMENT 1 + #ifndef DEVICE_TYPE #define DEVICE_TYPE ULONG #endif #define IRP_MJ_MAXIMUM_FUNCTION 0x1b +#define IRP_MJ_CREATE 0x00 +#define IRP_MJ_CREATE_NAMED_PIPE 0x01 +#define IRP_MJ_CLOSE 0x02 +#define IRP_MJ_READ 0x03 +#define IRP_MJ_WRITE 0x04 +#define IRP_MJ_QUERY_INFORMATION 0x05 +#define IRP_MJ_SET_INFORMATION 0x06 +#define IRP_MJ_QUERY_EA 0x07 +#define IRP_MJ_SET_EA 0x08 +#define IRP_MJ_FLUSH_BUFFERS 0x09 +#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a +#define IRP_MJ_SET_VOLUME_INFORMATION 0x0b +#define IRP_MJ_DIRECTORY_CONTROL 0x0c +#define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d #define IRP_MJ_DEVICE_CONTROL 0x0e +#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f +#define IRP_MJ_SHUTDOWN 0x10 +#define IRP_MJ_LOCK_CONTROL 0x11 +#define IRP_MJ_CLEANUP 0x12 +#define IRP_MJ_CREATE_MAILSLOT 0x13 +#define IRP_MJ_QUERY_SECURITY 0x14 +#define IRP_MJ_SET_SECURITY 0x15 +#define IRP_MJ_POWER 0x16 +#define IRP_MJ_SYSTEM_CONTROL 0x17 +#define IRP_MJ_DEVICE_CHANGE 0x18 +#define IRP_MJ_QUERY_QUOTA 0x19 +#define IRP_MJ_SET_QUOTA 0x1a +#define IRP_MJ_PNP 0x1b + +#define IRP_QUOTA_CHARGED 0x01 +#define IRP_ALLOCATED_MUST_SUCCEED 0x02 +#define IRP_ALLOCATED_FIXED_SIZE 0x04 +#define IRP_LOOKASIDE_ALLOCATION 0x08 typedef struct _DEVICE_OBJECT { CSHORT Type; @@ -877,13 +932,16 @@ PVOID WINAPI ExAllocatePoolWithQuotaTag(POOL_TYPE,SIZE_T,ULONG); void WINAPI ExFreePool(PVOID); void WINAPI ExFreePoolWithTag(PVOID,ULONG); +PIRP WINAPI IoAllocateIrp(CCHAR,BOOLEAN); NTSTATUS WINAPI IoCreateDevice(DRIVER_OBJECT*,ULONG,UNICODE_STRING*,DEVICE_TYPE,ULONG,BOOLEAN,DEVICE_OBJECT**); NTSTATUS WINAPI IoCreateDriver(UNICODE_STRING*,PDRIVER_INITIALIZE); NTSTATUS WINAPI IoCreateSymbolicLink(UNICODE_STRING*,UNICODE_STRING*); void WINAPI IoDeleteDevice(DEVICE_OBJECT*); void WINAPI IoDeleteDriver(DRIVER_OBJECT*); NTSTATUS WINAPI IoDeleteSymbolicLink(UNICODE_STRING*); +void WINAPI IoFreeIrp(IRP*); PEPROCESS WINAPI IoGetCurrentProcess(void); +void WINAPI IoInitializeIrp(IRP*,USHORT,CCHAR); PKTHREAD WINAPI KeGetCurrentThread(void); void WINAPI KeQuerySystemTime(LARGE_INTEGER*); diff --git a/include/dplay.h b/include/dplay.h index 855fc50497d..2294ba851fa 100644 --- a/include/dplay.h +++ b/include/dplay.h @@ -275,6 +275,9 @@ typedef const DPSESSIONDESC2* LPCDPSESSIONDESC2; #define DPSESSION_PASSWORDREQUIRED 0x00000400 #define DPSESSION_MULTICASTSERVER 0x00000800 #define DPSESSION_CLIENTSERVER 0x00001000 +#define DPSESSION_DIRECTPLAYPROTOCOL 0x00002000 +#define DPSESSION_NOPRESERVEORDER 0x00004000 +#define DPSESSION_OPTIMIZELATENCY 0x00008000 typedef struct tagDPLCONNECTION { @@ -392,7 +395,7 @@ typedef BOOL (CALLBACK *LPDPENUMSESSIONSCALLBACK)( extern HRESULT WINAPI DirectPlayEnumerateA( LPDPENUMDPCALLBACKA, LPVOID ); extern HRESULT WINAPI DirectPlayEnumerateW( LPDPENUMDPCALLBACKW, LPVOID ); -extern HRESULT WINAPI DirectPlayCreate( LPGUID lpGUID, LPDIRECTPLAY2 *lplpDP, IUnknown *pUnk); +extern HRESULT WINAPI DirectPlayCreate( LPGUID lpGUID, LPDIRECTPLAY *lplpDP, IUnknown *pUnk ); typedef BOOL (CALLBACK *LPDPENUMPLAYERSCALLBACK)( DPID dpId, @@ -1061,6 +1064,20 @@ DECLARE_INTERFACE_(IDirectPlay4,IDirectPlay3) /* DirectPlay::Connect */ #define DPCONNECT_RETURNSTATUS (DPENUMSESSIONS_RETURNSTATUS) +/* DirectPlay::GetCaps and DirectPlay::GetPlayerCaps */ +#define DPCAPS_ISHOST 0x00000002 +#define DPCAPS_GROUPOPTIMIZED 0x00000008 +#define DPCAPS_KEEPALIVEOPTIMIZED 0x00000010 +#define DPCAPS_GUARANTEEDOPTIMIZED 0x00000020 +#define DPCAPS_GUARANTEEDSUPPORTED 0x00000040 +#define DPCAPS_SIGNINGSUPPORTED 0x00000080 +#define DPCAPS_ENCRYPTIONSUPPORTED 0x00000100 +#define DPPLAYERCAPS_LOCAL 0x00000800 +#define DPCAPS_ASYNCCANCELSUPPORTED 0x00001000 +#define DPCAPS_ASYNCCANCELALLSUPPORTED 0x00002000 +#define DPCAPS_SENDTIMEOUTSUPPORTED 0x00004000 +#define DPCAPS_SENDPRIORITYSUPPORTED 0x00008000 +#define DPCAPS_ASYNCSUPPORTED 0x00010000 /** DirectPlay system messages **/ diff --git a/include/gdiplusenums.h b/include/gdiplusenums.h index 53401bd6895..bc52bd5d732 100644 --- a/include/gdiplusenums.h +++ b/include/gdiplusenums.h @@ -227,6 +227,14 @@ enum StringAlignment StringAlignmentFar = 2 }; +enum StringDigitSubstitute +{ + StringDigitSubstituteUser = 0, + StringDigitSubstituteNone = 1, + StringDigitSubstituteNational = 2, + StringDigitSubstituteTraditional = 3 +}; + enum StringFormatFlags { StringFormatFlagsDirectionRightToLeft = 0x00000001, @@ -346,6 +354,7 @@ typedef enum EmfType EmfType; typedef enum CompositingMode CompositingMode; typedef enum TextRenderingHint TextRenderingHint; typedef enum StringAlignment StringAlignment; +typedef enum StringDigitSubstitute StringDigitSubstitute; typedef enum StringTrimming StringTrimming; typedef enum FontStyle FontStyle; typedef enum StringFormatFlags StringFormatFlags; diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h index c82b69dc147..4293f6429e2 100644 --- a/include/gdiplusflat.h +++ b/include/gdiplusflat.h @@ -33,10 +33,13 @@ GpStatus WINGDIPAPI GdipCreatePen2(GpBrush*,REAL,GpUnit,GpPen**); GpStatus WINGDIPAPI GdipDeletePen(GpPen*); GpStatus WINGDIPAPI GdipGetPenBrushFill(GpPen*,GpBrush**); GpStatus WINGDIPAPI GdipGetPenColor(GpPen*,ARGB*); +GpStatus WINGDIPAPI GdipGetPenCustomStartCap(GpPen*,GpCustomLineCap**); +GpStatus WINGDIPAPI GdipGetPenCustomEndCap(GpPen*,GpCustomLineCap**); GpStatus WINGDIPAPI GdipGetPenDashArray(GpPen*,REAL*,INT); GpStatus WINGDIPAPI GdipGetPenDashCount(GpPen*,INT*); GpStatus WINGDIPAPI GdipGetPenDashOffset(GpPen*,REAL*); GpStatus WINGDIPAPI GdipGetPenDashStyle(GpPen*,GpDashStyle*); +GpStatus WINGDIPAPI GdipGetPenMode(GpPen*,GpPenAlignment*); GpStatus WINGDIPAPI GdipSetPenBrushFill(GpPen*,GpBrush*); GpStatus WINGDIPAPI GdipSetPenColor(GpPen*,ARGB); GpStatus WINGDIPAPI GdipSetPenCustomEndCap(GpPen*,GpCustomLineCap*); @@ -48,6 +51,7 @@ GpStatus WINGDIPAPI GdipSetPenDashStyle(GpPen*,GpDashStyle); GpStatus WINGDIPAPI GdipSetPenEndCap(GpPen*,GpLineCap); GpStatus WINGDIPAPI GdipSetPenLineCap197819(GpPen*,GpLineCap,GpLineCap,GpDashCap); GpStatus WINGDIPAPI GdipSetPenLineJoin(GpPen*,GpLineJoin); +GpStatus WINGDIPAPI GdipSetPenMode(GpPen*,GpPenAlignment); GpStatus WINGDIPAPI GdipSetPenMiterLimit(GpPen*,REAL); GpStatus WINGDIPAPI GdipSetPenStartCap(GpPen*,GpLineCap); GpStatus WINGDIPAPI GdipSetPenWidth(GpPen*,REAL); @@ -326,6 +330,10 @@ GpStatus WINGDIPAPI GdipDeleteCustomLineCap(GpCustomLineCap*); GpStatus WINGDIPAPI GdipSetCustomLineCapStrokeCaps(GpCustomLineCap*,GpLineCap, GpLineCap); GpStatus WINGDIPAPI GdipGetCustomLineCapBaseCap(GpCustomLineCap*,GpLineCap*); +GpStatus WINGDIPAPI GdipGetCustomLineCapBaseInset(GpCustomLineCap*,REAL*); +GpStatus WINGDIPAPI GdipGetCustomLineCapStrokeJoin(GpCustomLineCap*,GpLineJoin*); +GpStatus WINGDIPAPI GdipSetCustomLineCapStrokeJoin(GpCustomLineCap*,GpLineJoin); +GpStatus WINGDIPAPI GdipGetCustomLineCapWidthScale(GpCustomLineCap*,REAL*); GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap*,INT,INT,ARGB*); GpStatus WINGDIPAPI GdipBitmapSetPixel(GpBitmap*,INT,INT,ARGB); @@ -431,18 +439,25 @@ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyList(GpFontCollection*, INT, GpStatus WINGDIPAPI GdipCreateStringFormat(INT,LANGID,GpStringFormat**); GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat*); GpStatus WINGDIPAPI GdipStringFormatGetGenericDefault(GpStringFormat **); +GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **); GpStatus WINGDIPAPI GdipGetStringFormatAlign(GpStringFormat*,StringAlignment*); +GpStatus WINGDIPAPI GdipGetStringFormatDigitSubstitution(GDIPCONST GpStringFormat*,LANGID*, + StringDigitSubstitute*); GpStatus WINGDIPAPI GdipGetStringFormatFlags(GDIPCONST GpStringFormat*, INT*); GpStatus WINGDIPAPI GdipGetStringFormatHotkeyPrefix(GDIPCONST GpStringFormat*,INT*); GpStatus WINGDIPAPI GdipGetStringFormatLineAlign(GpStringFormat*,StringAlignment*); GpStatus WINGDIPAPI GdipGetStringFormatMeasurableCharacterRangeCount( GDIPCONST GpStringFormat*, INT*); +GpStatus WINGDIPAPI GdipGetStringFormatTabStopCount(GDIPCONST GpStringFormat*,INT*); +GpStatus WINGDIPAPI GdipGetStringFormatTabStops(GDIPCONST GpStringFormat*,INT,REAL*,REAL*); GpStatus WINGDIPAPI GdipGetStringFormatTrimming(GpStringFormat*,StringTrimming*); GpStatus WINGDIPAPI GdipSetStringFormatAlign(GpStringFormat*,StringAlignment); +GpStatus WINGDIPAPI GdipSetStringFormatDigitSubstitution(GpStringFormat*,LANGID,StringDigitSubstitute); GpStatus WINGDIPAPI GdipSetStringFormatHotkeyPrefix(GpStringFormat*,INT); GpStatus WINGDIPAPI GdipSetStringFormatLineAlign(GpStringFormat*,StringAlignment); GpStatus WINGDIPAPI GdipSetStringFormatMeasurableCharacterRanges( GpStringFormat*, INT, GDIPCONST CharacterRange*); +GpStatus WINGDIPAPI GdipSetStringFormatTabStops(GpStringFormat*,REAL,INT,GDIPCONST REAL*); GpStatus WINGDIPAPI GdipSetStringFormatTrimming(GpStringFormat*,StringTrimming); GpStatus WINGDIPAPI GdipCloneStringFormat(GDIPCONST GpStringFormat*,GpStringFormat**); diff --git a/include/intshcut.h b/include/intshcut.h index 54c2f2d1c19..71c75143b97 100644 --- a/include/intshcut.h +++ b/include/intshcut.h @@ -19,7 +19,7 @@ #ifndef __WINE_INTSHCUT_H #define __WINE_INTSHCUT_H -/* FIXME: #include */ +#include #define INTSHCUTAPI @@ -27,6 +27,74 @@ extern "C" { #endif +#define E_FLAGS MAKE_SCODE(SEVERITY_ERROR,FACILITY_ITF,0x1000) +#define IS_E_EXEC_FAILED MAKE_SCODE(SEVERITY_ERROR,FACILITY_ITF,0x2002) +#define URL_E_INVALID_SYNTAX MAKE_SCODE(SEVERITY_ERROR,FACILITY_ITF,0x1001) +#define URL_E_UNREGISTERED_PROTOCOL MAKE_SCODE(SEVERITY_ERROR,FACILITY_ITF,0x1002) + +typedef enum iurl_seturl_flags { + IURL_SETURL_FL_GUESS_PROTOCOL=1, + IURL_SETURL_FL_USE_DEFAULT_PROTOCOL, + ALL_IURL_SETURL_FLAGS=(IURL_SETURL_FL_GUESS_PROTOCOL|IURL_SETURL_FL_USE_DEFAULT_PROTOCOL) +} IURL_SETURL_FLAGS; + +typedef enum iurl_invokecommand_flags { + IURL_INVOKECOMMAND_FL_ALLOW_UI=1, + IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB, + ALL_IURL_INVOKECOMMAND_FLAGS=(IURL_INVOKECOMMAND_FL_ALLOW_UI|IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB) +} IURL_INVOKECOMMAND_FLAGS; + +typedef struct urlinvokecommandinfoA { + DWORD dwcbSize; + DWORD dwFlags; + HWND hwndParent; + LPCSTR pcszVerb; +} URLINVOKECOMMANDINFOA, *PURLINVOKECOMMANDINFOA; +typedef const URLINVOKECOMMANDINFOA CURLINVOKECOMMANDINFOA; +typedef const URLINVOKECOMMANDINFOA *PCURLINVOKECOMMANDINFOA; + +typedef struct urlinvokecommandinfoW { + DWORD dwcbSize; + DWORD dwFlags; + HWND hwndParent; + LPCWSTR pcszVerb; +} URLINVOKECOMMANDINFOW, *PURLINVOKECOMMANDINFOW; +typedef const URLINVOKECOMMANDINFOW CURLINVOKECOMMANDINFOW; +typedef const URLINVOKECOMMANDINFOW *PCURLINVOKECOMMANDINFOW; + +#define INTERFACE IUniformResourceLocatorA +DECLARE_INTERFACE_(IUniformResourceLocatorA,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, VOID **ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IUniformResourceLocatorA methods ***/ + STDMETHOD(SetURL)(THIS_ LPCSTR pcszURL, DWORD dwInFlags) PURE; + STDMETHOD(GetURL)(THIS_ LPSTR *ppszURL) PURE; + STDMETHOD(InvokeCommand)(THIS_ PURLINVOKECOMMANDINFOA pURLCommandInfo) PURE; +}; +#undef INTERFACE + +#define INTERFACE IUniformResourceLocatorW +DECLARE_INTERFACE_(IUniformResourceLocatorW,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, VOID **ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** IUniformResourceLocatorW methods ***/ + STDMETHOD(SetURL)(THIS_ LPCWSTR pcszURL, DWORD dwInFlags) PURE; + STDMETHOD(GetURL)(THIS_ LPWSTR *ppszURL) PURE; + STDMETHOD(InvokeCommand)(THIS_ PURLINVOKECOMMANDINFOW pURLCommandInfo) PURE; +}; +#undef INTERFACE + +DECL_WINELIB_TYPE_AW(URLINVOKECOMMANDINFO) +DECL_WINELIB_TYPE_AW(PURLINVOKECOMMANDINFO) +DECL_WINELIB_TYPE_AW(CURLINVOKECOMMANDINFO) +DECL_WINELIB_TYPE_AW(PCURLINVOKECOMMANDINFO) + BOOL WINAPI InetIsOffline(DWORD); #ifdef __cplusplus diff --git a/include/lmaccess.h b/include/lmaccess.h index b3372d7bcc5..c29a40c4700 100644 --- a/include/lmaccess.h +++ b/include/lmaccess.h @@ -449,6 +449,7 @@ typedef struct _LOCALGROUP_USERS_INFO_0 { #define LOCALGROUP_COMMENT_PARMNUM 2 NET_API_STATUS WINAPI NetGetDCName(LPCWSTR,LPCWSTR,LPBYTE*); +NET_API_STATUS WINAPI NetGroupEnum(LPCWSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD); NET_API_STATUS WINAPI NetLocalGroupAdd(LPCWSTR,DWORD,LPBYTE,LPDWORD); NET_API_STATUS WINAPI NetLocalGroupAddMember(LPCWSTR,LPCWSTR,PSID); NET_API_STATUS WINAPI NetLocalGroupAddMembers(LPCWSTR,LPCWSTR,DWORD,LPBYTE,DWORD); diff --git a/include/lmwksta.h b/include/lmwksta.h index 6ccb70469cc..6bc2faff626 100644 --- a/include/lmwksta.h +++ b/include/lmwksta.h @@ -83,6 +83,7 @@ NET_API_STATUS WINAPI NetWkstaTransportDel(LMSTR,LMSTR,DWORD); NET_API_STATUS WINAPI NetWkstaTransportEnum(LMSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD); NET_API_STATUS WINAPI NetWkstaUserGetInfo(LMSTR,DWORD,LPBYTE*); NET_API_STATUS WINAPI NetWkstaUserSetInfo(LMSTR,DWORD,LPBYTE,LPDWORD); +NET_API_STATUS WINAPI NetWkstaUserEnum(LMSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD); #ifdef __cplusplus } diff --git a/include/ras.h b/include/ras.h index 82efcdab650..f90d25ad896 100644 --- a/include/ras.h +++ b/include/ras.h @@ -55,10 +55,6 @@ extern "C" { #define RASDT_Parallel "PARALLEL" #define RASDT_PPPoE "PPPoE" -#define RASBASE 600 -#define ERROR_BUFFER_TOO_SMALL (RASBASE+3) -#define ERROR_INVALID_SIZE (RASBASE+32) - typedef struct tagRASDEVINFOA { DWORD dwSize; CHAR szDeviceType[ RAS_MaxDeviceType + 1 ]; diff --git a/include/intshcut.h b/include/raserror.h similarity index 70% copy from include/intshcut.h copy to include/raserror.h index 54c2f2d1c19..ad38cd3258d 100644 --- a/include/intshcut.h +++ b/include/raserror.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Francois Gouget + * Copyright (C) 2008 Stefan Leichter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,21 +16,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __WINE_INTSHCUT_H -#define __WINE_INTSHCUT_H +#ifndef __WINE_RASERROR_H +#define __WINE_RASERROR_H -/* FIXME: #include */ +#define RASBASE 600 +#define ERROR_BUFFER_TOO_SMALL (RASBASE+3) +#define ERROR_INVALID_SIZE (RASBASE+32) +#define ERROR_RASMAN_CANNOT_INITIALIZE (RASBASE+111) -#define INTSHCUTAPI - -#ifdef __cplusplus -extern "C" { #endif - -BOOL WINAPI InetIsOffline(DWORD); - -#ifdef __cplusplus -} -#endif - -#endif /* __WINE_INTSHCUT_H */ diff --git a/include/uuids.h b/include/uuids.h index 344957f1bb1..54a30fc2de2 100644 --- a/include/uuids.h +++ b/include/uuids.h @@ -45,6 +45,7 @@ OUR_GUID_ENTRY(MEDIASUBTYPE_YVYU, 0x55595659, 0x0000, 0x0010, OUR_GUID_ENTRY(MEDIASUBTYPE_UYVY, 0x59565955, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71) OUR_GUID_ENTRY(MEDIASUBTYPE_Y211, 0x31313259, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71) OUR_GUID_ENTRY(MEDIASUBTYPE_YV12, 0x32315659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71) +OUR_GUID_ENTRY(MEDIASUBTYPE_AYUV, 0x56555941, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71) OUR_GUID_ENTRY(MEDIASUBTYPE_CLJR, 0x524a4c43, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71) OUR_GUID_ENTRY(MEDIASUBTYPE_IF09, 0x39304649, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71) OUR_GUID_ENTRY(MEDIASUBTYPE_CPLA, 0x414c5043, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71) diff --git a/include/wine/test.h b/include/wine/test.h index 02fc3912276..62d8c3addcc 100644 --- a/include/wine/test.h +++ b/include/wine/test.h @@ -476,17 +476,18 @@ static void usage( const char *argv0 ) /* main function */ int main( int argc, char **argv ) { - char *p; + char p[128]; setvbuf (stdout, NULL, _IONBF, 0); winetest_argc = argc; winetest_argv = argv; - if ((p = getenv( "WINETEST_PLATFORM" ))) winetest_platform = strdup(p); - if ((p = getenv( "WINETEST_DEBUG" ))) winetest_debug = atoi(p); - if ((p = getenv( "WINETEST_INTERACTIVE" ))) winetest_interactive = atoi(p); - if ((p = getenv( "WINETEST_REPORT_SUCCESS"))) report_success = atoi(p); + if (GetEnvironmentVariableA( "WINETEST_PLATFORM", p, sizeof(p) )) winetest_platform = strdup(p); + if (GetEnvironmentVariableA( "WINETEST_DEBUG", p, sizeof(p) )) winetest_debug = atoi(p); + if (GetEnvironmentVariableA( "WINETEST_INTERACTIVE", p, sizeof(p) )) winetest_interactive = atoi(p); + if (GetEnvironmentVariableA( "WINETEST_REPORT_SUCCESS", p, sizeof(p) )) report_success = atoi(p); + if (!argv[1]) { if (winetest_testlist[0].name && !winetest_testlist[1].name) /* only one test */ diff --git a/include/winhttp.h b/include/winhttp.h index dab9bbaa7b9..4c647683dfe 100644 --- a/include/winhttp.h +++ b/include/winhttp.h @@ -436,6 +436,7 @@ typedef int INTERNET_SCHEME, *LPINTERNET_SCHEME; #define WINHTTP_AUTH_TARGET_SERVER 0x00000000 #define WINHTTP_AUTH_TARGET_PROXY 0x00000001 +#define WINHTTP_TIME_FORMAT_BUFSIZE 62 typedef struct { diff --git a/programs/cmd/wcmdmain.c b/programs/cmd/wcmdmain.c index 8d09967f661..454bd3ccc9d 100644 --- a/programs/cmd/wcmdmain.c +++ b/programs/cmd/wcmdmain.c @@ -601,10 +601,21 @@ void WCMD_execute (WCHAR *command, WCHAR *redirects, /* Move copy of the command onto the heap so it can be expanded */ new_cmd = HeapAlloc( GetProcessHeap(), 0, MAXSTRING * sizeof(WCHAR)); + if (!new_cmd) + { + WINE_ERR("Could not allocate memory for new_cmd\n"); + return; + } strcpyW(new_cmd, command); /* Move copy of the redirects onto the heap so it can be expanded */ new_redir = HeapAlloc( GetProcessHeap(), 0, MAXSTRING * sizeof(WCHAR)); + if (!new_redir) + { + WINE_ERR("Could not allocate memory for new_redir\n"); + HeapFree( GetProcessHeap(), 0, new_cmd ); + return; + } /* If piped output, send stdout to the pipe by appending >filename to redirects */ if (piped) { @@ -2086,6 +2097,11 @@ WCHAR *WCMD_ReadAndParseLine(WCHAR *optionalcmd, CMD_LIST **output, HANDLE readF /* Allocate working space for a command read from keyboard, file etc */ if (!extraSpace) extraSpace = HeapAlloc(GetProcessHeap(), 0, (MAXSTRING+1) * sizeof(WCHAR)); + if (!extraSpace) + { + WINE_ERR("Could not allocate memory for extraSpace\n"); + return NULL; + } /* If initial command read in, use that, otherwise get input from handle */ if (optionalcmd != NULL) { diff --git a/programs/taskmgr/Da.rc b/programs/taskmgr/Da.rc index 54ee078fb2f..fb9bab07a79 100644 --- a/programs/taskmgr/Da.rc +++ b/programs/taskmgr/Da.rc @@ -171,20 +171,6 @@ END Dialog */ -IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "Om Opgavebehandler" -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Opgavebehandler 1.0\nOphavsret 1999 - 2001 tilhører\nBrian Palmer (brianp@reactos.org)\nOversat af\nJens Albretsen (jens@albretsen.dk)", - IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,53,20, - 200,50 - 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 | @@ -497,5 +483,4 @@ BEGIN ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "Sætter processen til under normal prioritet" ID_PROCESS_PAGE_SETPRIORITY_LOW "Sætter processen til lav prioritet" - IDS_LICENSE "Dette program er fri programvare; du kan redistribuere det i henhold til vilkårene i 'GNU Lesser General Public License', udgivet af 'the Free Software Foundation'; enten version 2.1 af licensen, eller (hvis du ønsker) en nyere version.\r\n\r\nDette program distribueres med et håb om at det er nyttigt, men UDEN ENHVER FORM FOR GARANTI; ikke engang garanti for HANDELSDYGTIGHED eller EGNETHED FOR ET SPECIELT FORMÅL. Se 'GNU Lesser General Public License' for detaljer.\r\n\r\nDu skal have fået en kopi af 'GNU Lesser General Public License' sammen med programmet; hvis ikke, skriv til 'the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA'." END diff --git a/programs/taskmgr/De.rc b/programs/taskmgr/De.rc index c2886be1996..4f12f728747 100644 --- a/programs/taskmgr/De.rc +++ b/programs/taskmgr/De.rc @@ -166,20 +166,6 @@ END Dialog */ -IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "Über Task-Manager" -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 | @@ -481,5 +467,4 @@ BEGIN ID_PROCESS_PAGE_SETPRIORITY_NORMAL "Setzt den Prozess in die NORMAL-Prioritätsklasse" ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "Setzt den Prozess in die NIEDRIGER ALS NORMAL-Prioritätsklasse" ID_PROCESS_PAGE_SETPRIORITY_LOW "Setzt den Prozess in die NIEDRIG-Prioritätsklasse" - 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 Lesser General Public License for more details.\r\n\r\nYou should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA." END diff --git a/programs/taskmgr/En.rc b/programs/taskmgr/En.rc index bc160e3523e..8694588cf79 100644 --- a/programs/taskmgr/En.rc +++ b/programs/taskmgr/En.rc @@ -171,20 +171,6 @@ END Dialog */ -IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "About Task Manager" -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 | @@ -497,5 +483,4 @@ BEGIN ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "Sets process to the BELOW NORMAL priority class" ID_PROCESS_PAGE_SETPRIORITY_LOW "Sets process to the LOW priority class" - 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 Lesser General Public License for more details.\r\n\r\nYou should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA." END diff --git a/programs/taskmgr/Fr.rc b/programs/taskmgr/Fr.rc index 4a9bf3dd31c..d1c348808d4 100644 --- a/programs/taskmgr/Fr.rc +++ b/programs/taskmgr/Fr.rc @@ -172,20 +172,6 @@ END Dialog */ -IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "À propos du gestionnaire des tâches" -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Gestionnaire des tâches 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 | @@ -498,5 +484,4 @@ BEGIN ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "Place le processus dans la classe de priorité INFÉRIEURE À LA NORMALE" ID_PROCESS_PAGE_SETPRIORITY_LOW "Place le processus dans la classe de priorité BASSE" - IDS_LICENSE "Ce programme est libre, vous pouvez la redistribuer et/ou le modifier selon les termes de la Licence Publique Générale GNU Limitée publiée par la Free Software Foundation (version 2.1 ou bien toute autre version ultérieure choisie par vous).\r\n\r\nCe programme est distribuée car potentiellement utile, mais SANS AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties de commercialisation ou d'adaptation dans un but spécifique. Reportez-vous à la Licence Publique Générale GNU Limitée pour plus de détails.\r\n\r\nVous devez avoir reçu une copie de la Licence Publique Générale GNU Limitée en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, États-Unis." END diff --git a/programs/taskmgr/Ja.rc b/programs/taskmgr/Ja.rc index d630269bd88..2754be56962 100644 --- a/programs/taskmgr/Ja.rc +++ b/programs/taskmgr/Ja.rc @@ -172,20 +172,6 @@ END Dialog */ -IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "ƒ^ƒXƒN ƒ}ƒl�[ƒWƒƒ ‚̃o�[ƒWƒ‡ƒ“�î•ñ" -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 | @@ -498,5 +484,4 @@ BEGIN ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "ƒvƒ�ƒZƒX‚Ì—D�æƒNƒ‰ƒX‚ð ’Ê�íˆÈ‰º ‚É�ݒ肵‚Ü‚·�B" ID_PROCESS_PAGE_SETPRIORITY_LOW "ƒvƒ�ƒZƒX‚Ì—D�æƒNƒ‰ƒX‚ð ’á ‚É�ݒ肵‚Ü‚·�B" - 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 Lesser General Public License for more details.\r\n\r\nYou should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA." END diff --git a/programs/taskmgr/Ko.rc b/programs/taskmgr/Ko.rc index 00e05b6659f..7cc399b88d0 100644 --- a/programs/taskmgr/Ko.rc +++ b/programs/taskmgr/Ko.rc @@ -171,20 +171,6 @@ END Dialog */ -IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "ÀÛ¾÷ °ü¸®ÀÚ Á¤º¸" -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "ÀÛ¾÷ °ü¸®ÀÚ v1.0\nCopyright (C) 1999 - 2001\nby Brian Palmer (brianp@reactos.org)", - IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,53,28, - 122,26 - DEFPUSHBUTTON "È®ÀÎ",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 | @@ -497,5 +483,4 @@ BEGIN 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 Lesser General Public License for more details.\r\n\r\nYou should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA." END diff --git a/programs/taskmgr/Nl.rc b/programs/taskmgr/Nl.rc index e498d25c337..1529341dcdf 100644 --- a/programs/taskmgr/Nl.rc +++ b/programs/taskmgr/Nl.rc @@ -166,20 +166,6 @@ END Dialog */ -IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "Over Task Manager" -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 | @@ -481,5 +467,4 @@ BEGIN ID_PROCESS_PAGE_SETPRIORITY_NORMAL "Zet het proces in de NORMAAL-prioriteitsklasse" ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "Zet het proces in de LAGER DAN NORMAAL-prioriteitsklasse" ID_PROCESS_PAGE_SETPRIORITY_LOW "Zet het proces in de LAGE-prioriteitsklasse" - 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 Lesser General Public License for more details.\r\n\r\nYou should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA." END diff --git a/programs/taskmgr/No.rc b/programs/taskmgr/No.rc index 006be944bb9..f25eadc2696 100644 --- a/programs/taskmgr/No.rc +++ b/programs/taskmgr/No.rc @@ -171,20 +171,6 @@ END Dialog */ -IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "Om Oppgavebehandler" -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Oppgavebehandler 1.0\nKopirett 1999 - 2001 tilhører\nBrian Palmer (brianp@reactos.org)\nOversatt av\nAlexander N. Sørnes (alex@thehandofagony.com)", - IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,53,20, - 200,50 - 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 | @@ -497,5 +483,4 @@ BEGIN ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "Gir prosessen under normal prioritet" ID_PROCESS_PAGE_SETPRIORITY_LOW "Gir prosessen lav prioritet" - IDS_LICENSE "Dette programmer er fri programvare; du kan redistribuere det i henhold til vilkårene i 'GNU Lesser General Public License', utgitt av 'the Free Software Foundation'; enten versjon 2.1 av lisensen, eller (hvis du ønsker) en nyere versjon.\r\n\r\nDette programmet distribueres med et håp om at det er nyttig, men UTEN ENHVER FORM FOR GARANTI; ikke engang garanti for HANDELSDYKTIGHET eller EGNETHET FOR ET SPESIELT FORMÅL. Se 'GNU Lesser General Public License' for detaljer.\r\n\r\nDu skal ha fått en kopi av 'GNU Lesser General Public License' sammen med programmet; hvis ikke, skriv til 'the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA'." END diff --git a/programs/taskmgr/Pl.rc b/programs/taskmgr/Pl.rc index 1d827f5c9bd..14537096c12 100644 --- a/programs/taskmgr/Pl.rc +++ b/programs/taskmgr/Pl.rc @@ -172,20 +172,6 @@ END Dialog */ -IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "Mened¿er zadañ - informacje" -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Mened¿er zadañ v1.0\nCopyright (C) 1999 - 2001\nBrian 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 | @@ -497,5 +483,4 @@ BEGIN ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "Ustala priorytet procesu na poni¿ej normalnego" ID_PROCESS_PAGE_SETPRIORITY_LOW "Ustala priorytet procesu na niski" - 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 Lesser General Public License for more details.\r\n\r\nYou should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA." END diff --git a/programs/taskmgr/Ru.rc b/programs/taskmgr/Ru.rc index 10b8caee92f..e9d657bd23e 100644 --- a/programs/taskmgr/Ru.rc +++ b/programs/taskmgr/Ru.rc @@ -171,20 +171,6 @@ 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 | @@ -202,9 +188,9 @@ 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 + PUSHBUTTON "&Íîâàÿ çàäà÷à...",IDC_NEWTASK,177,189,63,14 + PUSHBUTTON "Ï&åðåêëþ÷èòüñÿ",IDC_SWITCHTO,111,189,63,14,WS_DISABLED + PUSHBUTTON "Ñíÿòü &çàäà÷ó",IDC_ENDTASK,45,189,63,14,WS_DISABLED END IDD_PROCESS_PAGE DIALOG DISCARDABLE 0, 0, 247, 210 @@ -364,65 +350,65 @@ BEGIN WS_DISABLED | WS_TABSTOP,175,119,41,10 END -IDD_COLUMNS_DIALOG DIALOG DISCARDABLE 0, 0, 195, 199 +IDD_COLUMNS_DIALOG DIALOG DISCARDABLE 20, 20, 244, 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 + DEFPUSHBUTTON "OK",IDOK,132,176,50,14 + PUSHBUTTON "Îòìåíà",IDCANCEL,186,176,50,14 LTEXT "Âûáåðèòå ñòîëáöû, êîòîðûå ïîÿâÿòñÿ íà ñòðàíèöå ïðîöåññîâ äèñïåò÷åðà çàäà÷.", - IDC_STATIC,7,7,181,17 + IDC_STATIC,7,4,227,19 CONTROL "&Èìÿ îáðàçà",IDC_IMAGENAME,"Button",BS_AUTOCHECKBOX | - WS_DISABLED | WS_TABSTOP,7,28,56,10 + WS_DISABLED | WS_TABSTOP,7,26,105,10 CONTROL "Èäåíòè&ô. ïðîöåññà (PID)",IDC_PID,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,39,88,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,37,105,10 CONTROL "&Çàãðóçêà ÖÏ",IDC_CPUUSAGE,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,50,53,10 + WS_TABSTOP,7,48,105,10 CONTROL "&Âðåìÿ ÖÏ",IDC_CPUTIME,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,61,48,10 + WS_TABSTOP,7,59,105,10 CONTROL "&Ïàìÿòü - èñïîëüçîâàíèå",IDC_MEMORYUSAGE,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,72,63,10 + WS_TABSTOP,7,70,105,10 CONTROL "Ïàìÿòü - èçìå&íåíèå",IDC_MEMORYUSAGEDELTA,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,83,82,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,81,105,10 CONTROL "Ïàìÿòü - &ìàêñèìóì",IDC_PEAKMEMORYUSAGE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,94,82,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,92,105,10 CONTROL "&Îøèáîê ñòðàíèöû",IDC_PAGEFAULTS,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,105,53,10 + WS_TABSTOP,7,103,105,10 CONTROL "Îá&úåêòû USER",IDC_USEROBJECTS,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,116,62,10 + WS_TABSTOP,7,114,105,10 CONTROL "×èñëî ÷òåíèé",IDC_IOREADS,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,127,49,10 + WS_TABSTOP,7,125,105,10 CONTROL "Ïðî÷èòàíî áàéò",IDC_IOREADBYTES,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,138,65,10 + BS_AUTOCHECKBOX | WS_TABSTOP,7,136,105,10 CONTROL "Êîä ñå&àíñà",IDC_SESSIONID,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,149,50,10 + WS_TABSTOP,7,147,105,10 CONTROL "Èì&ÿ ïîëüçîâàòåëÿ",IDC_USERNAME,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,160,51,10 + WS_TABSTOP,7,158,105,10 CONTROL "Îøèáîê &ñòðàíèöû - èçìåíåíèå",IDC_PAGEFAULTSDELTA,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,107,28,72,10 + BS_AUTOCHECKBOX | WS_TABSTOP,118,26,120,10 CONTROL "Îáúåì âèðòó&àëüíîé ïàìÿòè",IDC_VIRTUALMEMORYSIZE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,107,39,77,10 + BS_AUTOCHECKBOX | WS_TABSTOP,118,37,120,10 CONTROL "Âû&ãðóæàåìûé ïóë",IDC_PAGEDPOOL,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,107,50,53,10 + WS_TABSTOP,118,48,120,10 CONTROL "Íåâûãðóæàåìûé ï&óë",IDC_NONPAGEDPOOL,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,107,61,67,10 + BS_AUTOCHECKBOX | WS_TABSTOP,118,59,120,10 CONTROL "&Áàçîâûé ïðèîðèòåò",IDC_BASEPRIORITY,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,107,72,55,10 + BS_AUTOCHECKBOX | WS_TABSTOP,118,70,120,10 CONTROL "Ñ÷åò÷èê &äåñêðèïòîðîâ",IDC_HANDLECOUNT,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,107,83,59,10 + WS_TABSTOP,118,81,120,10 CONTROL "Ñ&÷åò÷èê ïîòîêîâ",IDC_THREADCOUNT,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,107,94,59,10 + WS_TABSTOP,118,92,120,10 CONTROL "Îáú&åêòû GDI",IDC_GDIOBJECTS,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,107,105,55,10 + WS_TABSTOP,118,103,120,10 CONTROL "×èñëî çàïèñåé",IDC_IOWRITES,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,107,116,49,10 + WS_TABSTOP,118,114,120,10 CONTROL "Çàïèñàíî áàéò",IDC_IOWRITEBYTES,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,107,127,65,10 + BS_AUTOCHECKBOX | WS_TABSTOP,118,125,120,10 CONTROL "Ïðî÷èé ââîä-âûâîä",IDC_IOOTHER,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,107,138,46,10 + WS_TABSTOP,118,136,120,10 CONTROL "Ïðî÷èõ áàéò ïðè ââîäå-âûâîäå",IDC_IOOTHERBYTES,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,107,149,65,10 + BS_AUTOCHECKBOX | WS_TABSTOP,118,147,120,10 END /* @@ -433,7 +419,7 @@ STRINGTABLE DISCARDABLE BEGIN IDS_APP_TITLE "Äèñïåò÷åð çàäà÷" IDC_TASKMGR "Äèñïåò÷åð çàäà÷" - IDS_RUNDLG_CAPTION "Create New Task" + IDS_RUNDLG_CAPTION "Ñîçäàòü íîâóþ çàäà÷ó" END STRINGTABLE DISCARDABLE @@ -497,5 +483,4 @@ BEGIN 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/Si.rc b/programs/taskmgr/Si.rc index ff7ed9b32ce..670189b4ed8 100644 --- a/programs/taskmgr/Si.rc +++ b/programs/taskmgr/Si.rc @@ -173,20 +173,6 @@ END Dialog */ -IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "O Upravitelju opravil" -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Upravitelj opravil v1.0\nCopyright (C) 1999 - 2001\nby Brian Palmer (brianp@reactos.org)", - IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,53,28, - 122,26 - DEFPUSHBUTTON "V redu",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 | @@ -499,7 +485,6 @@ BEGIN ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "Dodeli proces v PODPOVPREČNI prioritetni razred" ID_PROCESS_PAGE_SETPRIORITY_LOW "Dodeli proces v NIZEK prioritetni razred" - 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 Lesser General Public License for more details.\r\n\r\nYou should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA." END #pragma code_page(default) diff --git a/programs/taskmgr/Tr.rc b/programs/taskmgr/Tr.rc index 7677cd378b1..ac22a611853 100644 --- a/programs/taskmgr/Tr.rc +++ b/programs/taskmgr/Tr.rc @@ -171,20 +171,6 @@ END Dialog */ -IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 259, 210 -STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU -CAPTION "Görev Yöneticisi Hakkýnda" -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Görev Yöneticisi s1.0\nTelif Hakký (C) 1999 - 2001\nby Brian Palmer (brianp@reactos.org)", - IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,53,28, - 122,26 - DEFPUSHBUTTON "Tamam",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 | @@ -497,5 +483,4 @@ BEGIN ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL "Süreci NORMAL ALTI öncelik sýnýfýnda çalýþmaya ayarlar" ID_PROCESS_PAGE_SETPRIORITY_LOW "Süreci DÜÞÜK öncelik sýnýfýnda çalýþmaya ayarlar" - 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 Lesser General Public License for more details.\r\n\r\nYou should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA." END diff --git a/programs/taskmgr/resource.h b/programs/taskmgr/resource.h index 4ff4427a611..cc9ac012d22 100644 --- a/programs/taskmgr/resource.h +++ b/programs/taskmgr/resource.h @@ -9,7 +9,6 @@ #define IDS_RUNDLG_CAPTION 110 #define IDD_TASKMGR_DIALOG 102 -#define IDD_ABOUTBOX 103 #define IDM_ABOUT 104 #define IDM_EXIT 105 #define IDD_APPLICATION_PAGE 106 @@ -67,7 +66,6 @@ #define IDC_CPU10 1029 #define IDC_PAGEFAULTS 1029 #define IDC_COMMIT_CHARGE_LIMIT 1029 -#define IDC_LICENSE_EDIT 1029 #define IDC_CPU11 1030 #define IDC_USEROBJECTS 1030 #define IDC_COMMIT_CHARGE_PEAK 1030 @@ -184,7 +182,6 @@ #define ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL 32813 #define ID_PROCESS_PAGE_SETPRIORITY_LOW 32814 #define ID_PROCESS_PAGE_DEBUGCHANNELS 32815 -#define IDS_LICENSE 32816 #define IDC_STATIC -1 /* diff --git a/programs/taskmgr/trayicon.c b/programs/taskmgr/trayicon.c index e088f3f702b..25a5121097b 100644 --- a/programs/taskmgr/trayicon.c +++ b/programs/taskmgr/trayicon.c @@ -26,13 +26,13 @@ #include #include #include -#include #include #include - +#include + +#include "wine/unicode.h" #include "taskmgr.h" #include "perfdata.h" -#include "shellapi.h" HICON TrayIcon_GetProcessorUsageIcon(void) { @@ -140,23 +140,24 @@ done: BOOL TrayIcon_ShellAddTrayIcon(void) { - NOTIFYICONDATA nid; + NOTIFYICONDATAW nid; HICON hIcon = NULL; BOOL bRetVal; + WCHAR wszCPU_Usage[] = {'C','P','U',' ','U','s','a','g','e',':',' ','%','d','%','%',0}; - memset(&nid, 0, sizeof(NOTIFYICONDATA)); + memset(&nid, 0, sizeof(NOTIFYICONDATAW)); hIcon = TrayIcon_GetProcessorUsageIcon(); - nid.cbSize = sizeof(NOTIFYICONDATA); + nid.cbSize = sizeof(NOTIFYICONDATAW); nid.hWnd = hMainWnd; nid.uID = 0; nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; nid.uCallbackMessage = WM_ONTRAYICON; nid.hIcon = hIcon; - wsprintf(nid.szTip, _T("CPU Usage: %d%%"), PerfDataGetProcessorUsage()); + wsprintfW(nid.szTip, wszCPU_Usage, PerfDataGetProcessorUsage()); - bRetVal = Shell_NotifyIcon(NIM_ADD, &nid); + bRetVal = Shell_NotifyIconW(NIM_ADD, &nid); if (hIcon) DestroyIcon(hIcon); @@ -166,41 +167,42 @@ BOOL TrayIcon_ShellAddTrayIcon(void) BOOL TrayIcon_ShellRemoveTrayIcon(void) { - NOTIFYICONDATA nid; + NOTIFYICONDATAW nid; BOOL bRetVal; - memset(&nid, 0, sizeof(NOTIFYICONDATA)); + memset(&nid, 0, sizeof(NOTIFYICONDATAW)); - nid.cbSize = sizeof(NOTIFYICONDATA); + nid.cbSize = sizeof(NOTIFYICONDATAW); nid.hWnd = hMainWnd; nid.uID = 0; nid.uFlags = 0; nid.uCallbackMessage = WM_ONTRAYICON; - bRetVal = Shell_NotifyIcon(NIM_DELETE, &nid); + bRetVal = Shell_NotifyIconW(NIM_DELETE, &nid); return bRetVal; } BOOL TrayIcon_ShellUpdateTrayIcon(void) { - NOTIFYICONDATA nid; + NOTIFYICONDATAW nid; HICON hIcon = NULL; BOOL bRetVal; + WCHAR wszCPU_Usage[] = {'C','P','U',' ','U','s','a','g','e',':',' ','%','d','%','%',0}; - memset(&nid, 0, sizeof(NOTIFYICONDATA)); + memset(&nid, 0, sizeof(NOTIFYICONDATAW)); hIcon = TrayIcon_GetProcessorUsageIcon(); - nid.cbSize = sizeof(NOTIFYICONDATA); + nid.cbSize = sizeof(NOTIFYICONDATAW); nid.hWnd = hMainWnd; nid.uID = 0; nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; nid.uCallbackMessage = WM_ONTRAYICON; nid.hIcon = hIcon; - wsprintf(nid.szTip, _T("CPU Usage: %d%%"), PerfDataGetProcessorUsage()); + wsprintfW(nid.szTip, wszCPU_Usage, PerfDataGetProcessorUsage()); - bRetVal = Shell_NotifyIcon(NIM_MODIFY, &nid); + bRetVal = Shell_NotifyIconW(NIM_MODIFY, &nid); if (hIcon) DestroyIcon(hIcon); diff --git a/programs/winecfg/theme.c b/programs/winecfg/theme.c index abd016d7744..cdab531d2ce 100644 --- a/programs/winecfg/theme.c +++ b/programs/winecfg/theme.c @@ -554,7 +554,7 @@ static void set_color_from_theme(WCHAR *keyName, COLORREF color) keyNameSize = WideCharToMultiByte(CP_ACP, 0, keyName, -1, keyNameA, 0, NULL, NULL); keyNameA = HeapAlloc(GetProcessHeap(), 0, keyNameSize); - WideCharToMultiByte(CP_ACP, 0, keyName, -1, keyNameA, -1, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, keyName, -1, keyNameA, keyNameSize, NULL, NULL); for (i=0; iup && entry->up->etype==ET_SHELL) { - IShellFolder* folder = entry->up->folder; - WCHAR buffer[MAX_PATH]; + LPITEMIDLIST idl = NULL; - HRESULT hr = path_from_pidlW(folder, entry->pidl, buffer, MAX_PATH); - - if (SUCCEEDED(hr)) { - LPITEMIDLIST pidl; - ULONG len; - - hr = IShellFolder_ParseDisplayName(Globals.iDesktop, hwnd, NULL, buffer, &len, &pidl, NULL); - - if (SUCCEEDED(hr)) - return pidl; + while (entry->up) { + idl = ILCombine(ILClone(entry->pidl), idl); + entry = entry->up; } + + return idl; } else if (entry->etype == ET_WINDOWS) { TCHAR path[MAX_PATH]; diff --git a/programs/winetest/main.c b/programs/winetest/main.c index 04eaae48831..045845a3552 100644 --- a/programs/winetest/main.c +++ b/programs/winetest/main.c @@ -659,25 +659,18 @@ int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, cmdLine = strtok (NULL, whitespace); } if (!submit) { - static CHAR platform_windows[] = "WINETEST_PLATFORM=windows", - platform_wine[] = "WINETEST_PLATFORM=wine", - debug_yes[] = "WINETEST_DEBUG=1", - interactive_no[] = "WINETEST_INTERACTIVE=0", - report_success_no[] = "WINETEST_REPORT_SUCCESS=0"; - CHAR *platform; - report (R_STATUS, "Starting up"); if (!running_on_visible_desktop ()) report (R_FATAL, "Tests must be run on a visible desktop"); - platform = running_under_wine () ? platform_wine : platform_windows; - - if (reset_env && (putenv (platform) || - putenv (debug_yes) || - putenv (interactive_no) || - putenv (report_success_no))) - report (R_FATAL, "Could not reset environment"); + if (reset_env) + { + SetEnvironmentVariableA( "WINETEST_PLATFORM", running_under_wine () ? "wine" : "windows" ); + SetEnvironmentVariableA( "WINETEST_DEBUG", "1" ); + SetEnvironmentVariableA( "WINETEST_INTERACTIVE", "0" ); + SetEnvironmentVariableA( "WINETEST_REPORT_SUCCESS", "0" ); + } if (!tag) { if (!interactive) diff --git a/programs/winhlp32/Da.rc b/programs/winhlp32/Da.rc index 886943ae381..927fc32079f 100644 --- a/programs/winhlp32/Da.rc +++ b/programs/winhlp32/Da.rc @@ -73,8 +73,6 @@ FONT 8, "MS Shell Dlg" CAPTION "Index" { LISTBOX IDC_INDEXLIST, 10, 10, 180, 150, LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_BORDER - PUSHBUTTON "&OK", IDOK, 40, 170, 50, 12 - PUSHBUTTON "&Annuller", IDCANCEL, 120, 170, 50, 12 } /* Strings */ diff --git a/programs/winhlp32/De.rc b/programs/winhlp32/De.rc index 1be4838fd1e..49cda6d152e 100644 --- a/programs/winhlp32/De.rc +++ b/programs/winhlp32/De.rc @@ -72,8 +72,6 @@ FONT 8, "MS Shell Dlg" CAPTION "Index" { LISTBOX IDC_INDEXLIST, 10, 10, 180, 150, LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_BORDER - PUSHBUTTON "&OK", IDOK, 40, 170, 50, 12 - PUSHBUTTON "&Abbrechen", IDCANCEL, 120, 170, 50, 12 } /* Strings */ diff --git a/programs/winhlp32/En.rc b/programs/winhlp32/En.rc index 7c46e2b2879..1276f9ccc1e 100644 --- a/programs/winhlp32/En.rc +++ b/programs/winhlp32/En.rc @@ -72,8 +72,6 @@ FONT 8, "MS Shell Dlg" CAPTION "Index" { LISTBOX IDC_INDEXLIST, 10, 10, 180, 150, LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_BORDER - PUSHBUTTON "&OK", IDOK, 40, 170, 50, 12 - PUSHBUTTON "&Cancel", IDCANCEL, 120, 170, 50, 12 } IDD_SEARCH DIALOG DISCARDABLE 0, 0, 200, 190 LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT diff --git a/programs/winhlp32/Fr.rc b/programs/winhlp32/Fr.rc index 2c6d112c2ea..60acba8b5f8 100644 --- a/programs/winhlp32/Fr.rc +++ b/programs/winhlp32/Fr.rc @@ -75,8 +75,6 @@ FONT 8, "MS Shell Dlg" CAPTION "Index" { LISTBOX IDC_INDEXLIST, 10, 10, 180, 150, LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_BORDER - PUSHBUTTON "&OK", IDOK, 40, 170, 50, 12 - PUSHBUTTON "&Annuler", IDCANCEL, 120, 170, 50, 12 } /* Strings */ diff --git a/programs/winhlp32/Ko.rc b/programs/winhlp32/Ko.rc index 7839bacf9d0..3b059741b91 100644 --- a/programs/winhlp32/Ko.rc +++ b/programs/winhlp32/Ko.rc @@ -73,8 +73,6 @@ FONT 8, "MS Shell Dlg" CAPTION "À妽º" { LISTBOX IDC_INDEXLIST, 10, 10, 180, 150, LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_BORDER - PUSHBUTTON "È®ÀÎ(&O)", IDOK, 40, 170, 50, 12 - PUSHBUTTON "Ãë¼Ò(&C)", IDCANCEL, 120, 170, 50, 12 } IDD_SEARCH DIALOG DISCARDABLE 0, 0, 200, 190 LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT diff --git a/programs/winhlp32/Nl.rc b/programs/winhlp32/Nl.rc index 78d9a68150d..6a8747a859e 100644 --- a/programs/winhlp32/Nl.rc +++ b/programs/winhlp32/Nl.rc @@ -72,8 +72,6 @@ FONT 8, "MS Shell Dlg" CAPTION "Index" { LISTBOX IDC_INDEXLIST, 10, 10, 180, 150, LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_BORDER - PUSHBUTTON "&OK", IDOK, 40, 170, 50, 12 - PUSHBUTTON "&Annuleren", IDCANCEL, 120, 170, 50, 12 } IDD_SEARCH DIALOG DISCARDABLE 0, 0, 200, 190 LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL diff --git a/programs/winhlp32/No.rc b/programs/winhlp32/No.rc index b31df015e1a..1632da6d427 100644 --- a/programs/winhlp32/No.rc +++ b/programs/winhlp32/No.rc @@ -71,8 +71,6 @@ FONT 8, "MS Shell Dlg" CAPTION "Innhold" { LISTBOX IDC_INDEXLIST, 10, 10, 180, 150, LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_BORDER - PUSHBUTTON "&OK", IDOK, 40, 170, 50, 12 - PUSHBUTTON "&Avbryt", IDCANCEL, 120, 170, 50, 12 } /* Strings */ diff --git a/programs/winhlp32/Pl.rc b/programs/winhlp32/Pl.rc index b8234273e64..17d5d22e346 100644 --- a/programs/winhlp32/Pl.rc +++ b/programs/winhlp32/Pl.rc @@ -73,8 +73,6 @@ FONT 8, "MS Shell Dlg" CAPTION "Indeks" { LISTBOX IDC_INDEXLIST, 10, 10, 180, 150, LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_BORDER - PUSHBUTTON "&OK", IDOK, 40, 170, 50, 12 - PUSHBUTTON "&Anuluj", IDCANCEL, 120, 170, 50, 12 } /* Strings */ diff --git a/programs/winhlp32/Ru.rc b/programs/winhlp32/Ru.rc index 78aa4813600..af0097b7eea 100644 --- a/programs/winhlp32/Ru.rc +++ b/programs/winhlp32/Ru.rc @@ -71,8 +71,6 @@ FONT 8, "MS Shell Dlg" CAPTION "Óêàçàòåëü" { LISTBOX IDC_INDEXLIST, 10, 10, 180, 150, LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_BORDER - PUSHBUTTON "&OK", IDOK, 40, 170, 50, 12 - PUSHBUTTON "&Îòìåíà", IDCANCEL, 120, 170, 50, 12 } /* Strings */ diff --git a/programs/winhlp32/Si.rc b/programs/winhlp32/Si.rc index f28b9f1c028..f1a213d9ab9 100644 --- a/programs/winhlp32/Si.rc +++ b/programs/winhlp32/Si.rc @@ -73,8 +73,6 @@ FONT 8, "MS Shell Dlg" CAPTION "Indeks" { LISTBOX IDC_INDEXLIST, 10, 10, 180, 150, LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_BORDER - PUSHBUTTON "&V redu", IDOK, 40, 170, 50, 12 - PUSHBUTTON "&Prekliči", IDCANCEL, 120, 170, 50, 12 } /* Strings */ diff --git a/programs/winhlp32/winhelp.c b/programs/winhlp32/winhelp.c index d65a752c308..d3f4d1405a5 100644 --- a/programs/winhlp32/winhelp.c +++ b/programs/winhlp32/winhelp.c @@ -1572,12 +1572,6 @@ struct index_data /************************************************************************** * WINHELP_IndexDlgProc * - * Index dialog callback function. - * - * nResult passed to EndDialog: - * 1: CANCEL button - * >1: valid offset value +2. - * EndDialog itself can return 0 (error). */ INT_PTR CALLBACK WINHELP_IndexDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { diff --git a/tools/wine.inf.in b/tools/wine.inf.in index da5020d96be..4d10778ddd5 100644 --- a/tools/wine.inf.in +++ b/tools/wine.inf.in @@ -274,12 +274,12 @@ HKLM,Software\Microsoft\DirectPlay\Service Providers\Serial Connection For Direc HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"APPDATA",,"%16410%" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"ComSpec",0x00020000,"%11%\cmd.exe" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"LOCALAPPDATA",,"%16412%" -HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"PATH",0x00020000,"%11%;%10%" +HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"PATH",0x00020002,"%11%;%10%" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"ProgramFiles",,"%16422%" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"SystemDrive",2,"c:" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"SYSTEMROOT",,"%10%" -HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"TEMP",0x00020000,"%10%\temp" -HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"TMP",0x00020000,"%10%\temp" +HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"TEMP",0x00020002,"%10%\temp" +HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"TMP",0x00020002,"%10%\temp" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"windir",0x00020000,"%10%" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"winsysdir",,"%11%" @@ -2213,6 +2213,8 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G" 11,,msi.dll,1 11,,msiexec.exe,1 11,,msimtf.dll,1 +11,,msisip.dll,1 +11,,mstask.dll,1 11,,msxml3.dll,1 11,,objsel.dll,1 11,,qcap.dll,1 -- 2.11.4.GIT