From beae8e892e92362167444d2dd1ea95424f2c1a8f Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Wed, 9 May 2007 00:49:17 +0200 Subject: [PATCH] push 735ae92a6c6e93f1d42ab1ae3fd17e22de57873e --- configure | 128 ++++++--- configure.ac | 29 +- dlls/Makedll.rules.in | 2 +- dlls/advapi32/service.c | 110 +++++++- dlls/browseui/browseui_main.c | 12 +- dlls/comctl32/tests/treeview.c | 13 +- dlls/comctl32/treeview.c | 4 +- dlls/ddraw/clipper.c | 76 ++---- dlls/ddraw/ddraw.c | 89 ++++--- dlls/ddraw/ddraw_private.h | 11 +- dlls/ddraw/device.c | 55 +++- dlls/ddraw/direct3d.c | 10 + dlls/ddraw/main.c | 3 + dlls/ddraw/surface.c | 10 +- dlls/ddraw/tests/dsurface.c | 553 +++++++++++++++++++++++++++++++++++++-- dlls/gdi32/dib.c | 2 + dlls/imagehlp/access.c | 1 - dlls/imagehlp/imagehlp_main.c | 1 - dlls/imagehlp/integrity.c | 1 - dlls/imagehlp/modify.c | 1 - dlls/infosoft/wordbreaker.c | 1 - dlls/inseng/inseng_main.c | 1 - dlls/itss/itss.c | 3 - dlls/itss/moniker.c | 4 - dlls/itss/storage.c | 4 - dlls/kernel32/Makefile.in | 1 + dlls/kernel32/actctx.c | 1 - dlls/kernel32/atom.c | 2 - dlls/kernel32/atom16.c | 1 - dlls/kernel32/computername.c | 1 - dlls/kernel32/cpu.c | 1 - dlls/kernel32/error16.c | 1 - dlls/kernel32/except.c | 1 - dlls/kernel32/file.c | 1 - dlls/kernel32/global16.c | 1 - dlls/kernel32/heap.c | 1 - dlls/kernel32/instr.c | 1 - dlls/kernel32/kernel_main.c | 49 +++- dlls/kernel32/ne_module.c | 1 - dlls/kernel32/oldconfig.c | 2 - dlls/kernel32/process.c | 1 - dlls/kernel32/resource.c | 2 - dlls/kernel32/selector.c | 1 - dlls/kernel32/stress.c | 1 - dlls/kernel32/string.c | 1 - dlls/kernel32/system.c | 1 - dlls/kernel32/thread.c | 1 - dlls/kernel32/toolhelp16.c | 1 - dlls/kernel32/virtual.c | 1 - dlls/kernel32/volume.c | 1 - dlls/kernel32/windebug.c | 1 - dlls/localui/localui.c | 125 ++++++++- dlls/localui/localui.h | 6 +- dlls/localui/localui.rc | 1 + dlls/localui/ui_De.rc | 54 ++++ dlls/localui/ui_En.rc | 13 + dlls/mshtml/nsembed.c | 76 ------ dlls/msi/action.c | 138 ++++++++-- dlls/msi/automation.c | 214 ++++++++++++++- dlls/msi/dialog.c | 34 ++- dlls/msi/events.c | 8 + dlls/msi/msipriv.h | 2 +- dlls/msi/msiserver.idl | 73 +++--- dlls/msi/msiserver_dispids.h | 6 + dlls/msi/package.c | 5 +- dlls/msi/script.c | 15 +- dlls/msi/tests/automation.c | 340 ++++++++++++++++++++++-- dlls/ntdll/signal_i386.c | 13 +- dlls/ole32/compobj.c | 149 +++++++---- dlls/ole32/errorinfo.c | 35 +++ dlls/ole32/ole2.c | 13 +- dlls/ole32/tests/compobj.c | 200 +++++++++++++- dlls/riched20/tests/editor.c | 1 + dlls/rsaenh/rsaenh.c | 20 +- dlls/rsaenh/tests/rsaenh.c | 40 +++ dlls/setupapi/misc.c | 57 +++- dlls/setupapi/query.c | 24 +- dlls/setupapi/tests/misc.c | 13 +- dlls/user32/dialog.c | 17 +- dlls/user32/tests/msg.c | 104 +++++++- dlls/user32/tests/resource.rc | 8 + dlls/wined3d/Makefile.in | 1 + dlls/wined3d/clipper.c | 203 ++++++++++++++ dlls/wined3d/device.c | 7 +- dlls/wined3d/surface.c | 154 ++++++++--- dlls/wined3d/surface_gdi.c | 14 +- dlls/wined3d/wined3d.spec | 1 + dlls/wined3d/wined3d_private.h | 18 ++ dlls/winmm/time.c | 17 +- include/winbase.h | 1 + include/wincrypt.h | 5 + include/wine/wined3d_interface.h | 58 ++++ include/winsvc.h | 26 +- tools/wine.inf | 2 +- tools/winegcc/winegcc.c | 6 +- 95 files changed, 2939 insertions(+), 579 deletions(-) create mode 100644 dlls/localui/ui_De.rc create mode 100644 dlls/wined3d/clipper.c diff --git a/configure b/configure index f2fb4beeae5..1d099010579 100755 --- a/configure +++ b/configure @@ -10385,66 +10385,69 @@ fi if test "$ac_cv_header_unicode_ubidi_h" = "yes" then saved_libs="$LIBS" - for i in ${ICU_LIB_DIR-/usr/lib}/libsicu ${ICU_LIB_DIR-/usr/lib}/libicu - do - TEST_ICUUC_LIB="${ICUUC_LIB-${i}uc.a}" - TEST_ICUDATA_LIB="${ICUDATA_LIB-${i}data.a}" - { echo "$as_me:$LINENO: checking whether can link with ICU libraries $TEST_ICUUC_LIB and $TEST_ICUDATA_LIB" >&5 -echo $ECHO_N "checking whether can link with ICU libraries $TEST_ICUUC_LIB and $TEST_ICUDATA_LIB... $ECHO_C" >&6; } - LIBS="$saved_libs $TEST_ICUUC_LIB $TEST_ICUDATA_LIB -lstdc++ -lgcc_s" - cat >conftest.$ac_ext <<_ACEOF + icu_libs="-lsicuuc -lsicudata -lstdc++ -lgcc_s" + if test -n "$ICU_LIB_DIR" + then + icu_libs="-L$ICU_LIB_DIR $icu_libs" + fi + { echo "$as_me:$LINENO: checking whether can link with ICU libraries" >&5 +echo $ECHO_N "checking whether can link with ICU libraries... $ECHO_C" >&6; } + LIBS="$saved_libs $icu_libs" + if test "$cross_compiling" = yes; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +else + cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include -int -main () -{ -ubidi_open() - ; - return 0; -} +main () { ubidi_open(); return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext +rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 + (eval "$ac_link") 2>&5 ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then cat >>confdefs.h <<\_ACEOF #define HAVE_ICU 1 _ACEOF - ICULIBS="$TEST_ICUUC_LIB $TEST_ICUDATA_LIB -lstdc++ -lgcc_s" + ICULIBS="$icu_libs" - { echo "$as_me:$LINENO: result: yes" >&5 + { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } else - echo "$as_me: failed program was:" >&5 + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - { echo "$as_me:$LINENO: result: no" >&5 +( exit $ac_status ) +{ echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext - done LIBS="$saved_libs" fi @@ -13672,6 +13675,67 @@ ac_res=`eval echo '${'$as_ac_var'}'` echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then LIBWINE_LDFLAGS="-Wl,--rpath,\\\$\$ORIGIN/\`\$(RELPATH) \$(bindir) \$(libdir)\`" +else + as_ac_var=`echo "ac_cv_cflags_-fPIC -Wl,-R,\$ORIGIN/../lib" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking whether the compiler supports -fPIC -Wl,-R,\$ORIGIN/../lib" >&5 +echo $ECHO_N "checking whether the compiler supports -fPIC -Wl,-R,\$ORIGIN/../lib... $ECHO_C" >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_wine_try_cflags_saved=$CFLAGS +CFLAGS="$CFLAGS -fPIC -Wl,-R,\$ORIGIN/../lib" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +CFLAGS=$ac_wine_try_cflags_saved +fi +ac_res=`eval echo '${'$as_ac_var'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_var'}'` = yes; then + LIBWINE_LDFLAGS="-Wl,-R,\\\$\$ORIGIN/\`\$(RELPATH) \$(bindir) \$(libdir)\`" +fi + fi diff --git a/configure.ac b/configure.ac index c82deae9330..60bf14f628c 100644 --- a/configure.ac +++ b/configure.ac @@ -604,18 +604,19 @@ dnl **** Check for the ICU library **** if test "$ac_cv_header_unicode_ubidi_h" = "yes" then saved_libs="$LIBS" - for i in ${ICU_LIB_DIR-/usr/lib}/libsicu ${ICU_LIB_DIR-/usr/lib}/libicu - do - TEST_ICUUC_LIB="${ICUUC_LIB-${i}uc.a}" - TEST_ICUDATA_LIB="${ICUDATA_LIB-${i}data.a}" - AC_MSG_CHECKING(whether can link with ICU libraries $TEST_ICUUC_LIB and $TEST_ICUDATA_LIB) - LIBS="$saved_libs $TEST_ICUUC_LIB $TEST_ICUDATA_LIB -lstdc++ -lgcc_s" - AC_TRY_LINK([#include ],[ubidi_open()], - [AC_DEFINE(HAVE_ICU,1,[Define to 1 if the ICU libraries are installed]) - AC_SUBST(ICULIBS,"$TEST_ICUUC_LIB $TEST_ICUDATA_LIB -lstdc++ -lgcc_s") - AC_MSG_RESULT(yes)], - [AC_MSG_RESULT(no)]) - done + icu_libs="-lsicuuc -lsicudata -lstdc++ -lgcc_s" + if test -n "$ICU_LIB_DIR" + then + icu_libs="-L$ICU_LIB_DIR $icu_libs" + fi + AC_MSG_CHECKING(whether can link with ICU libraries) + LIBS="$saved_libs $icu_libs" + AC_TRY_RUN([#include +main () { ubidi_open(); return 0; }], + [AC_DEFINE(HAVE_ICU,1,[Define to 1 if the ICU libraries are installed]) + AC_SUBST(ICULIBS,"$icu_libs") + AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no)],[AC_MSG_RESULT(no)]) LIBS="$saved_libs" fi @@ -1042,7 +1043,9 @@ case $host_os in [AC_SUBST(LDEXECFLAGS,["-Wl,--export-dynamic"])]) WINE_TRY_CFLAGS([-fPIC -Wl,--rpath,\$ORIGIN/../lib], - [LIBWINE_LDFLAGS="-Wl,--rpath,\\\$\$ORIGIN/\`\$(RELPATH) \$(bindir) \$(libdir)\`"]) + [LIBWINE_LDFLAGS="-Wl,--rpath,\\\$\$ORIGIN/\`\$(RELPATH) \$(bindir) \$(libdir)\`"], + [WINE_TRY_CFLAGS([-fPIC -Wl,-R,\$ORIGIN/../lib], + [LIBWINE_LDFLAGS="-Wl,-R,\\\$\$ORIGIN/\`\$(RELPATH) \$(bindir) \$(libdir)\`"])]) case $host_cpu in *i[[3456789]]86* | x86_64) diff --git a/dlls/Makedll.rules.in b/dlls/Makedll.rules.in index fe777841da7..31621754fd8 100644 --- a/dlls/Makedll.rules.in +++ b/dlls/Makedll.rules.in @@ -32,7 +32,7 @@ all: $(MODULE)$(DLLEXT) $(SUBDIRS) # Rules for .so files $(MODULE).so: $(MAINSPEC) $(ALL_OBJS) Makefile.in - $(WINEGCC) -B$(TOOLSDIR)/tools/winebuild -shared $(SRCDIR)/$(MAINSPEC) $(ALL_OBJS) $(SUBSYSTEM:%=-Wb,--subsystem,%) $(BASEADDRESS:%=-Wl,--image-base,%) -o $@ $(DELAYIMPORTS:%=-l%) $(IMPORTS:%=-l%) $(DELAYIMPORTS:%=-Wb,-d%) $(ALL_LIBS) + $(WINEGCC) -B$(TOOLSDIR)/tools/winebuild -shared $(SRCDIR)/$(MAINSPEC) $(ALL_OBJS) $(SUBSYSTEM:%=-Wb,--subsystem,%) $(DLLFILENAME:%=-Wb,-F,%) $(BASEADDRESS:%=-Wl,--image-base,%) -o $@ $(DELAYIMPORTS:%=-l%) $(IMPORTS:%=-l%) $(DELAYIMPORTS:%=-Wb,-d%) $(ALL_LIBS) # Rules for .dll files diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index 3979b061f65..22489a9a1a1 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -3,6 +3,7 @@ * * Copyright 1995 Sven Verdoolaege * Copyright 2005 Mike McCormack + * Copyright 2007 Rolf Kalbermatter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -53,6 +54,7 @@ typedef struct service_start_info_t #define WINESERV_STARTINFO 1 #define WINESERV_GETSTATUS 2 #define WINESERV_SENDCONTROL 3 +#define WINESERV_SETPID 4 typedef struct service_data_t { @@ -520,6 +522,41 @@ static BOOL service_get_status(HANDLE pipe, LPSERVICE_STATUS_PROCESS status) } /****************************************************************************** + * service_handle_set_processID + */ +static BOOL service_handle_set_processID(HANDLE pipe, service_data *service, DWORD dwProcessId) +{ + DWORD count, ret = ERROR_SUCCESS; + + TRACE("received control %d\n", dwProcessId); + service->status.dwProcessId = dwProcessId; + return WriteFile(pipe, &ret, sizeof ret , &count, NULL); +} + +/****************************************************************************** + * service_set_processID + */ +static BOOL service_set_processID(HANDLE pipe, DWORD dwprocessId, LPDWORD dwResult) +{ + DWORD cmd[2], count = 0; + BOOL r; + + cmd[0] = WINESERV_SETPID; + cmd[1] = dwprocessId; + r = WriteFile( pipe, cmd, sizeof cmd, &count, NULL ); + if (!r || count != sizeof cmd) + { + ERR("service protocol error - failed to write pipe!\n"); + return r; + } + r = ReadFile( pipe, dwResult, sizeof *dwResult, &count, NULL ); + if (!r || count != sizeof *dwResult) + ERR("service protocol error - failed to read pipe " + "r = %d count = %d!\n", r, count); + return r; +} + +/****************************************************************************** * service_send_control */ static BOOL service_send_control(HANDLE pipe, DWORD dwControl, DWORD *result) @@ -704,6 +741,9 @@ static DWORD WINAPI service_control_dispatcher(LPVOID arg) case WINESERV_SENDCONTROL: service_handle_control(pipe, service, req[1]); break; + case WINESERV_SETPID: + service_handle_set_processID(pipe, service, req[1]); + break; default: ERR("received invalid command %d length %d\n", req[0], req[1]); } @@ -1523,7 +1563,7 @@ BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs, { struct sc_service *hsvc; BOOL r = FALSE; - DWORD pid; + DWORD dwResult, dwProcessId = 0; SC_LOCK hLock; HANDLE handle = INVALID_HANDLE_VALUE; @@ -1544,15 +1584,15 @@ BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs, if (handle==INVALID_HANDLE_VALUE) { /* start the service process */ - if (service_start_process(hsvc, &pid)) + if (service_start_process(hsvc, &dwProcessId)) handle = service_open_pipe(hsvc->name); } if (handle != INVALID_HANDLE_VALUE) { - service_send_start_message(handle, lpServiceArgVectors, dwNumServiceArgs); + if (service_send_start_message(handle, lpServiceArgVectors, dwNumServiceArgs)) + r = service_set_processID(handle, dwProcessId, &dwResult); CloseHandle(handle); - r = TRUE; } UnlockServiceDatabase( hLock ); @@ -1995,9 +2035,36 @@ BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager, BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName, LPSTR lpDisplayName, LPDWORD lpcchBuffer) { - FIXME("%p %s %p %p\n", hSCManager, + struct sc_manager *hscm; + DWORD type, size; + LONG ret; + + TRACE("%p %s %p %p\n", hSCManager, debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer); - return FALSE; + + hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER); + if (!hscm) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + size = *lpcchBuffer; + ret = RegGetValueA(hscm->hkey, lpServiceName, "DisplayName", RRF_RT_REG_SZ, &type, lpDisplayName, &size); + if (ret) + { + if (lpDisplayName && *lpcchBuffer) *lpDisplayName = 0; + + if (ret == ERROR_MORE_DATA) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + *lpcchBuffer = size - 1; + } + else + SetLastError(ret); + return FALSE; + } + return TRUE; } /****************************************************************************** @@ -2006,9 +2073,36 @@ BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName, BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, LPWSTR lpDisplayName, LPDWORD lpcchBuffer) { - FIXME("%p %s %p %p\n", hSCManager, + struct sc_manager *hscm; + DWORD type, size; + LONG ret; + + TRACE("%p %s %p %p\n", hSCManager, debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer); - return FALSE; + + hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER); + if (!hscm) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + size = *lpcchBuffer * sizeof(WCHAR); + ret = RegGetValueW(hscm->hkey, lpServiceName, szDisplayName, RRF_RT_REG_SZ, &type, lpDisplayName, &size); + if (ret) + { + if (lpDisplayName && *lpcchBuffer) *lpDisplayName = 0; + + if (ret == ERROR_MORE_DATA) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + *lpcchBuffer = (size / sizeof(WCHAR)) - 1; + } + else + SetLastError(ret); + return FALSE; + } + return TRUE; } /****************************************************************************** diff --git a/dlls/browseui/browseui_main.c b/dlls/browseui/browseui_main.c index 27965547300..98b1424390e 100644 --- a/dlls/browseui/browseui_main.c +++ b/dlls/browseui/browseui_main.c @@ -126,8 +126,16 @@ static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock) { - FIXME("(%p, %s) - not implemented\n", iface, (fLock ? "TRUE" : "FALSE")); - return E_NOTIMPL; + ClassFactory *This = (ClassFactory *)iface; + + TRACE("(%p)->(%x)\n", This, fLock); + + if(fLock) + InterlockedIncrement(&BROWSEUI_refCount); + else + InterlockedDecrement(&BROWSEUI_refCount); + + return S_OK; } static const IClassFactoryVtbl ClassFactoryVtbl = { diff --git a/dlls/comctl32/tests/treeview.c b/dlls/comctl32/tests/treeview.c index 3c7e9f55dd1..3b33eab1d0f 100644 --- a/dlls/comctl32/tests/treeview.c +++ b/dlls/comctl32/tests/treeview.c @@ -90,8 +90,11 @@ static const struct message DoFocusTestSeq[] = { { WM_PARENTNOTIFY, sent|wparam|defwinproc, 0x00000001 }, { WM_KILLFOCUS, sent|defwinproc }, { WM_PAINT, sent|defwinproc }, + { WM_IME_SETCONTEXT, sent|defwinproc|optional }, { WM_COMMAND, sent|wparam|defwinproc, 0x01000000}, { WM_ERASEBKGND, sent|defwinproc }, + { WM_CTLCOLOREDIT, sent|defwinproc|optional }, + { WM_CTLCOLOREDIT, sent|defwinproc|optional }, { 0 } }; @@ -166,6 +169,8 @@ static const struct message TestGetSetTextColorSeq[] = { }; static const struct message TestGetSetToolTipsSeq[] = { + { WM_COMMAND, sent|wparam, 0x02000000 }, + { WM_PARENTNOTIFY, sent|wparam|defwinproc, 0x00020002 }, { TVM_SETTOOLTIPS, sent|wparam|lparam, 0x00000000, 0x00000000 }, { TVM_GETTOOLTIPS, sent|wparam|lparam, 0x00000000, 0x00000000 }, { 0 } @@ -467,6 +472,11 @@ static void TestGetSetTextColor(void) static void TestGetSetToolTips(void) { HWND hwndLastToolTip = NULL; + HWND hPopupTreeView; + + /* show even WS_POPUP treeview don't send NM_TOOLTIPSCREATED */ + hPopupTreeView = CreateWindow(WC_TREEVIEW, NULL, WS_POPUP|WS_VISIBLE, 0, 0, 100, 100, hMainWnd, NULL, NULL, NULL); + DestroyWindow(hPopupTreeView); /* Testing setting a NULL ToolTip */ SendMessage( hTree, TVM_SETTOOLTIPS, 0, 0 ); @@ -549,7 +559,7 @@ static void TestGetSet(void) flush_sequences(MsgSequences, NUM_MSG_SEQUENCES); TestGetSetToolTips(); ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, TestGetSetToolTipsSeq, - "TestGetSetToolTips", FALSE); + "TestGetSetToolTips", TRUE); /* TVM_GETUNICODEFORMAT and TVM_SETUNICODEFORMAT */ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES); @@ -611,6 +621,7 @@ static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa { NMHDR *pHdr = (NMHDR *)lParam; + ok(pHdr->code != NM_FIRST - 19, "Treeview should not send NM_TOOLTIPSCREATED\n"); if (pHdr->idFrom == 100) { NMTREEVIEWA *pTreeView = (LPNMTREEVIEWA) lParam; switch(pHdr->code) { diff --git a/dlls/comctl32/treeview.c b/dlls/comctl32/treeview.c index 8adf28bd3c0..40c053d85a6 100644 --- a/dlls/comctl32/treeview.c +++ b/dlls/comctl32/treeview.c @@ -4967,7 +4967,9 @@ TREEVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs) TREEVIEW_NotifyFormat(infoPtr, infoPtr->hwndNotify, NF_REQUERY); if (!(infoPtr->dwStyle & TVS_NOTOOLTIPS)) - infoPtr->hwndToolTip = COMCTL32_CreateToolTip(hwnd); + infoPtr->hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, WS_POPUP, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + hwnd, 0, 0, 0); if (infoPtr->dwStyle & TVS_CHECKBOXES) initialize_checkboxes(infoPtr); diff --git a/dlls/ddraw/clipper.c b/dlls/ddraw/clipper.c index be4ef9de68d..eb8a8dbd530 100644 --- a/dlls/ddraw/clipper.c +++ b/dlls/ddraw/clipper.c @@ -106,8 +106,9 @@ static ULONG WINAPI IDirectDrawClipperImpl_Release(IDirectDrawClipper *iface) { if (ref == 0) { - HeapFree(GetProcessHeap(), 0, This); - return 0; + IWineD3DClipper_Release(This->wineD3DClipper); + HeapFree(GetProcessHeap(), 0, This); + return 0; } else return ref; } @@ -131,15 +132,17 @@ static HRESULT WINAPI IDirectDrawClipperImpl_SetHwnd( LPDIRECTDRAWCLIPPER iface, DWORD dwFlags, HWND hWnd ) { IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface; + HRESULT hr; + TRACE("(%p)->(%08x,%p)\n", This, dwFlags, hWnd); - TRACE("(%p)->(0x%08x,0x%08x)\n", This, dwFlags, (DWORD)hWnd); - if( dwFlags ) { - FIXME("dwFlags = 0x%08x, not supported.\n",dwFlags); - return DDERR_INVALIDPARAMS; + hr = IWineD3DClipper_SetHWnd(This->wineD3DClipper, + dwFlags, + hWnd); + switch(hr) + { + case WINED3DERR_INVALIDCALL: return DDERR_INVALIDPARAMS; + default: return hr; } - - This->hWnd = hWnd; - return DD_OK; } /***************************************************************************** @@ -165,46 +168,12 @@ static HRESULT WINAPI IDirectDrawClipperImpl_GetClipList( LPDWORD lpdwSize) { IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface; - TRACE("(%p,%p,%p,%p)\n", This, lpRect, lpClipList, lpdwSize); - if (This->hWnd) - { - HDC hDC = GetDCEx(This->hWnd, NULL, DCX_WINDOW); - if (hDC) - { - HRGN hRgn = CreateRectRgn(0,0,0,0); - if (GetRandomRgn(hDC, hRgn, SYSRGN)) - { - if (GetVersion() & 0x80000000) - { - /* map region to screen coordinates */ - POINT org; - GetDCOrgEx( hDC, &org ); - OffsetRgn( hRgn, org.x, org.y ); - } - if (lpRect) - { - HRGN hRgnClip = CreateRectRgn(lpRect->left, lpRect->top, - lpRect->right, lpRect->bottom); - CombineRgn(hRgn, hRgn, hRgnClip, RGN_AND); - DeleteObject(hRgnClip); - } - *lpdwSize = GetRegionData(hRgn, *lpdwSize, lpClipList); - } - DeleteObject(hRgn); - ReleaseDC(This->hWnd, hDC); - } - return DD_OK; - } - else - { - static int warned = 0; - if (warned++ < 10) - FIXME("(%p,%p,%p,%p),stub!\n",This,lpRect,lpClipList,lpdwSize); - if (lpdwSize) *lpdwSize=0; - return DDERR_NOCLIPLIST; - } + return IWineD3DClipper_GetClipList(This->wineD3DClipper, + lpRect, + lpClipList, + lpdwSize); } /***************************************************************************** @@ -225,10 +194,10 @@ static HRESULT WINAPI IDirectDrawClipperImpl_SetClipList( LPDIRECTDRAWCLIPPER iface,LPRGNDATA lprgn,DWORD dwFlag ) { IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface; - static int warned = 0; - if (warned++ < 10 || lprgn == NULL) - FIXME("(%p,%p,%d),stub!\n",This,lprgn,dwFlag); - return DD_OK; + + return IWineD3DClipper_SetClipList(This->wineD3DClipper, + lprgn, + dwFlag); } /***************************************************************************** @@ -248,9 +217,8 @@ static HRESULT WINAPI IDirectDrawClipperImpl_GetHWnd( IDirectDrawClipperImpl *This = (IDirectDrawClipperImpl *)iface; TRACE("(%p)->(%p)\n", This, hWndPtr); - *hWndPtr = This->hWnd; - - return DD_OK; + return IWineD3DClipper_GetHWnd(This->wineD3DClipper, + hWndPtr); } /***************************************************************************** diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index a18b9adeb4c..36b3a955f92 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -1445,6 +1445,7 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, IWineD3DSurface *wineD3DSurface; HRESULT hr; void *tmp; + IWineD3DClipper *clipper = NULL; WINED3DSURFACE_DESC Desc; WINED3DFORMAT Format; @@ -1480,6 +1481,8 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, IWineD3DSurface_Release(wineD3DSurface); } + /* get the clipper */ + IWineD3DSurface_GetClipper(wineD3DSurface, &clipper); /* Get the surface properties */ Desc.Format = &Format; @@ -1514,6 +1517,8 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, if(hr != D3D_OK) return hr; + IWineD3DSurface_SetClipper(surfImpl->WineD3DSurface, clipper); + /* Update the IParent if it exists */ if(parImpl) { @@ -1530,6 +1535,10 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf, surfImpl->ImplType = This->ImplType; + if(clipper) + { + IWineD3DClipper_Release(clipper); + } return DDENUMRET_OK; } @@ -1783,8 +1792,7 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, Usage |= WINED3DUSAGE_RENDERTARGET; pDDSD->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY | - DDSCAPS_VISIBLE | - DDSCAPS_LOCALVIDMEM; + DDSCAPS_VISIBLE; } if (pDDSD->ddsCaps.dwCaps & (DDSCAPS_OVERLAY)) { @@ -1805,6 +1813,15 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, else if(pDDSD->ddsCaps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE) { Pool = WINED3DPOOL_MANAGED; + /* Managed textures have the system memory flag set */ + pDDSD->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } + else if(pDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) + { + /* Videomemory adds localvidmem, this is mutually exclusive with systemmemory + * and texturemanage + */ + pDDSD->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM; } Format = PixelFormat_DD2WineD3D(&pDDSD->u4.ddpfPixelFormat); @@ -1943,10 +1960,27 @@ IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, /* Anno 1602 stores the pitch right after surface creation, so make sure it's there. * I can't LockRect() the surface here because if OpenGL surfaces are in use, the - * WineD3DDevice might not be useable for 3D yet, so an extra method was created + * WineD3DDevice might not be useable for 3D yet, so an extra method was created. + * TODO: Test other fourcc formats */ - (*ppSurf)->surface_desc.dwFlags |= DDSD_PITCH; - (*ppSurf)->surface_desc.u1.lPitch = IWineD3DSurface_GetPitch((*ppSurf)->WineD3DSurface); + if(Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 || + Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) + { + (*ppSurf)->surface_desc.dwFlags |= DDSD_LINEARSIZE; + if(Format == WINED3DFMT_DXT1) + { + (*ppSurf)->surface_desc.u1.dwLinearSize = max(4, Width) * max(4, Height) / 2; + } + else + { + (*ppSurf)->surface_desc.u1.dwLinearSize = max(4, Width) * max(4, Height); + } + } + else + { + (*ppSurf)->surface_desc.dwFlags |= DDSD_PITCH; + (*ppSurf)->surface_desc.u1.lPitch = IWineD3DSurface_GetPitch((*ppSurf)->WineD3DSurface); + } /* Application passed a color key? Set it! */ if(pDDSD->dwFlags & DDSD_CKDESTOVERLAY) @@ -2303,43 +2337,22 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface, } } - /* No Width or no Height? Use the current window size or - * the original screen size + /* No Width or no Height? Use the original screen size */ if(!(desc2.dwFlags & DDSD_WIDTH) || !(desc2.dwFlags & DDSD_HEIGHT) ) { - HWND window; + /* Invalid for non-render targets */ + if(!(desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) + { + WARN("Creating a non-Primary surface without Width or Height info, returning DDERR_INVALIDPARAMS\n"); + *Surf = NULL; + return DDERR_INVALIDPARAMS; + } - /* Fallback: From WineD3D / original mode */ desc2.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT; desc2.dwWidth = Mode.Width; desc2.dwHeight = Mode.Height; - - hr = IWineD3DDevice_GetHWND(This->wineD3DDevice, - &window); - if( (hr == D3D_OK) && (window != 0) ) - { - RECT rect; - if(GetWindowRect(window, &rect) ) - { - /* This is a hack until I find a better solution */ - if( (rect.right - rect.left) <= 1 || - (rect.bottom - rect.top) <= 1 ) - { - FIXME("Wanted to get surface dimensions from window %p, but it has only " - "a size of %dx%d. Using full screen dimensions\n", - window, rect.right - rect.left, rect.bottom - rect.top); - } - else - { - /* Not sure if this is correct */ - desc2.dwWidth = rect.right - rect.left; - desc2.dwHeight = rect.bottom - rect.top; - TRACE("Using window %p's dimensions: %dx%d\n", window, desc2.dwWidth, desc2.dwHeight); - } - } - } } /* Mipmap count fixes */ @@ -3033,8 +3046,12 @@ DirectDrawCreateClipper(DWORD Flags, ICOM_INIT_INTERFACE(object, IDirectDrawClipper, IDirectDrawClipper_Vtbl); object->ref = 1; - object->hWnd = 0; - object->ddraw_owner = NULL; + object->wineD3DClipper = pWineDirect3DCreateClipper((IUnknown *) object); + if(!object->wineD3DClipper) + { + HeapFree(GetProcessHeap(), 0, object); + return E_OUTOFMEMORY; + } *Clipper = (IDirectDrawClipper *) object; return DD_OK; diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 8a04ad2657f..2c144f7b2fc 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -398,16 +398,15 @@ struct IDirectDrawClipperImpl ICOM_VFIELD_MULTI(IDirectDrawClipper); LONG ref; - /* IDirectDrawClipper fields */ - HWND hWnd; - - IDirectDrawImpl* ddraw_owner; - struct IDirectDrawClipperImpl* prev_ddraw; - struct IDirectDrawClipperImpl* next_ddraw; + IWineD3DClipper *wineD3DClipper; + IDirectDrawImpl *ddraw_owner; }; const IDirectDrawClipperVtbl IDirectDrawClipper_Vtbl; +typedef IWineD3DClipper* (WINAPI *fnWineDirect3DCreateClipper)(IUnknown *); +fnWineDirect3DCreateClipper pWineDirect3DCreateClipper; + /***************************************************************************** * IDirectDrawPalette implementation structure *****************************************************************************/ diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 30f80ad4785..63b06e82677 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -306,6 +306,17 @@ IDirect3DDeviceImpl_7_Release(IDirect3DDevice7 *iface) /* Restore the render targets */ if(This->OffScreenTarget) { + WINED3DVIEWPORT vp; + + vp.X = 0; + vp.Y = 0; + vp.Width = This->ddraw->d3d_target->surface_desc.dwWidth; + vp.Height = This->ddraw->d3d_target->surface_desc.dwHeight; + vp.MinZ = 0.0; + vp.MaxZ = 1.0; + IWineD3DDevice_SetViewport(This->wineD3DDevice, + &vp); + /* Set the device up to render to the front buffer since the back buffer will * vanish soon. */ @@ -4021,12 +4032,28 @@ IDirect3DDeviceImpl_7_GetTextureStageState(IDirect3DDevice7 *iface, Stage, WINED3DSAMP_MINFILTER, State); - /* Same for MAGFILTER */ + /* Magfilter has slightly different values */ case D3DTSS_MAGFILTER: - return IWineD3DDevice_GetSamplerState(This->wineD3DDevice, - Stage, - WINED3DSAMP_MAGFILTER, - State); + { + HRESULT hr; + WINED3DTEXTUREFILTERTYPE wined3dfilter; + hr = IWineD3DDevice_GetSamplerState(This->wineD3DDevice, + Stage, + WINED3DSAMP_MAGFILTER, + &wined3dfilter); + switch(wined3dfilter) + { + case WINED3DTEXF_POINT: *State = D3DTFG_POINT; break; + case WINED3DTEXF_LINEAR: *State = D3DTFG_LINEAR; break; + case WINED3DTEXF_ANISOTROPIC: *State = D3DTFG_ANISOTROPIC; break; + case WINED3DTEXF_FLATCUBIC: *State = D3DTFG_FLATCUBIC; break; + case WINED3DTEXF_GAUSSIANCUBIC: *State = D3DTFG_GAUSSIANCUBIC; break; + default: + ERR("Unexpected wined3d mag filter value %d\n", wined3dfilter); + *State = D3DTFG_POINT; + } + return hr; + } case D3DTSS_ADDRESS: case D3DTSS_ADDRESSU: @@ -4115,12 +4142,26 @@ IDirect3DDeviceImpl_7_SetTextureStageState(IDirect3DDevice7 *iface, Stage, WINED3DSAMP_MINFILTER, State); - /* Same for MAGFILTER */ + /* Magfilter has slightly different values */ case D3DTSS_MAGFILTER: + { + WINED3DTEXTUREFILTERTYPE wined3dfilter; + switch((D3DTEXTUREMAGFILTER) State) + { + case D3DTFG_POINT: wined3dfilter = WINED3DTEXF_POINT; break; + case D3DTFG_LINEAR: wined3dfilter = WINED3DTEXF_LINEAR; break; + case D3DTFG_FLATCUBIC: wined3dfilter = WINED3DTEXF_FLATCUBIC; break; + case D3DTFG_GAUSSIANCUBIC: wined3dfilter = WINED3DTEXF_GAUSSIANCUBIC; break; + case D3DTFG_ANISOTROPIC: wined3dfilter = WINED3DTEXF_ANISOTROPIC; break; + default: + ERR("Unexpected d3d7 mag filter type %d\n", State); + wined3dfilter = WINED3DTEXF_POINT; + } return IWineD3DDevice_SetSamplerState(This->wineD3DDevice, Stage, WINED3DSAMP_MAGFILTER, - State); + wined3dfilter); + } case D3DTSS_ADDRESS: IWineD3DDevice_SetSamplerState(This->wineD3DDevice, diff --git a/dlls/ddraw/direct3d.c b/dlls/ddraw/direct3d.c index 9f7e1366325..0ccb2c30c40 100644 --- a/dlls/ddraw/direct3d.c +++ b/dlls/ddraw/direct3d.c @@ -844,6 +844,7 @@ IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface, if(!(target->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) && (This->d3d_target != target)) { + WINED3DVIEWPORT vp; TRACE("(%p) Using %p as front buffer, %p as back buffer\n", This, This->d3d_target, target); hr = IWineD3DDevice_SetFrontBackBuffers(This->wineD3DDevice, This->d3d_target->WineD3DSurface, @@ -855,6 +856,15 @@ IDirect3DImpl_7_CreateDevice(IDirect3D7 *iface, IWineD3DDevice_SetRenderTarget(This->wineD3DDevice, 0, target->WineD3DSurface); + vp.X = 0; + vp.Y = 0; + vp.Width = target->surface_desc.dwWidth; + vp.Height = target->surface_desc.dwHeight; + vp.MinZ = 0.0; + vp.MaxZ = 1.0; + IWineD3DDevice_SetViewport(This->wineD3DDevice, + &vp); + object->OffScreenTarget = TRUE; } else diff --git a/dlls/ddraw/main.c b/dlls/ddraw/main.c index 1e83c5b0f53..46c383a74a8 100644 --- a/dlls/ddraw/main.c +++ b/dlls/ddraw/main.c @@ -172,7 +172,10 @@ DDRAW_Create(const GUID *guid, { hWineD3D = LoadLibraryA("wined3d"); if (hWineD3D) + { pWineDirect3DCreate = (fnWineDirect3DCreate) GetProcAddress(hWineD3D, "WineDirect3DCreate"); + pWineDirect3DCreateClipper = (fnWineDirect3DCreateClipper) GetProcAddress(hWineD3D, "WineDirect3DCreateClipper"); + } } if (!hWineD3D) diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index e99c2b84536..5f2652638d2 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -592,11 +592,11 @@ IDirectDrawSurfaceImpl_Lock(IDirectDrawSurface7 *iface, Flags); if(hr != D3D_OK) return hr; - /* Override the memory area and the pitch */ - DDSD->dwFlags |= DDSD_LPSURFACE; + /* Override the memory area. The pitch should be set already. Strangely windows + * does not set the LPSURFACE flag on locked surfaces !?!. + * DDSD->dwFlags |= DDSD_LPSURFACE; + */ DDSD->lpSurface = LockedRect.pBits; - DDSD->dwFlags |= DDSD_PITCH; - DDSD->u1.lPitch = LockedRect.Pitch; TRACE("locked surface returning description :\n"); if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(DDSD); @@ -1966,7 +1966,7 @@ IDirectDrawSurfaceImpl_SetClipper(IDirectDrawSurface7 *iface, if(oldClipper) IDirectDrawClipper_Release(ICOM_INTERFACE(oldClipper, IDirectDrawClipper)); - return DD_OK; + return IWineD3DSurface_SetClipper(This->WineD3DSurface, This->clipper->wineD3DClipper); } /***************************************************************************** diff --git a/dlls/ddraw/tests/dsurface.c b/dlls/ddraw/tests/dsurface.c index 537cb293973..653cf7e0322 100644 --- a/dlls/ddraw/tests/dsurface.c +++ b/dlls/ddraw/tests/dsurface.c @@ -4,6 +4,7 @@ * Copyright (C) 2005 Antoine Chavasse (a.chavasse@gmail.com) * Copyright (C) 2005 Christian Costa * Copyright 2005 Ivan Leo Puoti + * Copyright (C) 2007 Stefan Dösinger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -202,7 +203,7 @@ static void SrcColorKey32BlitTest(void) ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = 0xFF00FF; rc = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpSrc, NULL); ok(rc==DD_OK,"CreateSurface returned: %x\n",rc); - + rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); lpData = (LPDWORD)ddsd2.lpSurface; @@ -215,6 +216,7 @@ static void SrcColorKey32BlitTest(void) rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; lpData[0] = 0x77010203; lpData[1] = 0x00010203; @@ -227,6 +229,7 @@ static void SrcColorKey32BlitTest(void) rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; ok((lpData[0]==0x77010203)&&(lpData[1]==0x00010203)&&(lpData[2]==0xCCCCCCCC)&&(lpData[3]==0xCCCCCCCC), "Destination data after blitting is not correct\n"); @@ -317,6 +320,7 @@ static void SrcColorKey32BlitTest(void) rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; lpData[0] = 0x000000FF; /* Applies to src blt key in src surface */ lpData[1] = 0x00000000; /* Applies to dst blt key in src surface */ @@ -329,6 +333,7 @@ static void SrcColorKey32BlitTest(void) rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; lpData[0] = 0x55555555; lpData[1] = 0x55555555; @@ -345,6 +350,7 @@ static void SrcColorKey32BlitTest(void) rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; /* Should have copied src data unmodified to dst */ ok(lpData[0] == 0x000000FF && @@ -369,6 +375,7 @@ static void SrcColorKey32BlitTest(void) rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; ok(lpData[0] == 0x55555555 && /* Here the src key applied */ @@ -393,6 +400,7 @@ static void SrcColorKey32BlitTest(void) rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; ok(lpData[0] == 0x000000FF && @@ -419,6 +427,7 @@ static void SrcColorKey32BlitTest(void) /* Verify that the destination is unchanged */ rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; ok(lpData[0] == 0x55555555 && @@ -444,6 +453,7 @@ static void SrcColorKey32BlitTest(void) rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; /* DirectDraw uses the dest blit key from the SOURCE surface ! */ @@ -470,6 +480,7 @@ static void SrcColorKey32BlitTest(void) rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; ok(lpData[0] == 0x00FF0000 && @@ -496,6 +507,7 @@ static void SrcColorKey32BlitTest(void) /* Check for unchanged data */ rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; ok(lpData[0] == 0x00FF0000 && @@ -518,6 +530,7 @@ static void SrcColorKey32BlitTest(void) /* Modify the source data a bit to give some more conclusive results */ rc = IDirectDrawSurface_Lock(lpSrc, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; lpData[5] = 0x000000FF; /* Applies to src blt key in src surface */ rc = IDirectDrawSurface_Unlock(lpSrc, NULL); @@ -529,6 +542,7 @@ static void SrcColorKey32BlitTest(void) rc = IDirectDrawSurface_Lock(lpDst, NULL, &ddsd2, DDLOCK_WAIT, NULL); ok(rc==DD_OK,"Lock returned: %x\n",rc); + ok((ddsd2.dwFlags & DDSD_LPSURFACE) == 0, "Surface desc has LPSURFACE Flags set\n"); lpData = (LPDWORD)ddsd2.lpSurface; ok(lpData[0] == 0x00FF0000 && /* Masked by Destination key */ @@ -1028,7 +1042,7 @@ static void AttachmentTest(void) ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_BACKBUFFERCOUNT | DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; - U2(ddsd).dwBackBufferCount = 2; + ddsd.dwBackBufferCount = 2; hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface1, NULL); ok(hr==DD_OK,"CreateSurface returned: %x\n",hr); @@ -1137,7 +1151,7 @@ static void CubeMapTest(void) memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); - ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; ddsd.dwWidth = 128; ddsd.dwHeight = 128; @@ -1145,11 +1159,11 @@ static void CubeMapTest(void) ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES; /* D3DFMT_R5G6B5 */ - ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - ddsd.ddpfPixelFormat.dwRGBBitCount = 16; - ddsd.ddpfPixelFormat.dwRBitMask = 0xF800; - ddsd.ddpfPixelFormat.dwGBitMask = 0x07E0; - ddsd.ddpfPixelFormat.dwBBitMask = 0x001F; + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16; + U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800; + U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0; + U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F; hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL); ok(hr == DD_OK, "IDirectDraw7::CreateSurface returned %08x\n", hr); @@ -1171,7 +1185,7 @@ static void CubeMapTest(void) /* What happens if I do not specify any faces? */ memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); - ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; ddsd.dwWidth = 128; ddsd.dwHeight = 128; @@ -1179,11 +1193,11 @@ static void CubeMapTest(void) ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP; /* D3DFMT_R5G6B5 */ - ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - ddsd.ddpfPixelFormat.dwRGBBitCount = 16; - ddsd.ddpfPixelFormat.dwRBitMask = 0xF800; - ddsd.ddpfPixelFormat.dwGBitMask = 0x07E0; - ddsd.ddpfPixelFormat.dwBBitMask = 0x001F; + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16; + U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800; + U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0; + U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F; hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL); ok(hr == DDERR_INVALIDPARAMS, "IDirectDraw7::CreateSurface asking for a cube map without faces returned %08x\n", hr); @@ -1191,7 +1205,7 @@ static void CubeMapTest(void) /* Cube map faces without a cube map? */ memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); - ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; ddsd.dwWidth = 128; ddsd.dwHeight = 128; @@ -1199,18 +1213,18 @@ static void CubeMapTest(void) ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP_ALLFACES; /* D3DFMT_R5G6B5 */ - ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - ddsd.ddpfPixelFormat.dwRGBBitCount = 16; - ddsd.ddpfPixelFormat.dwRBitMask = 0xF800; - ddsd.ddpfPixelFormat.dwGBitMask = 0x07E0; - ddsd.ddpfPixelFormat.dwBBitMask = 0x001F; + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16; + U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800; + U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0; + U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F; hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL); ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7::CreateSurface returned %08x\n", hr); memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); - ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; ddsd.dwWidth = 128; ddsd.dwHeight = 128; @@ -1218,11 +1232,11 @@ static void CubeMapTest(void) ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP_POSITIVEX; /* D3DFMT_R5G6B5 */ - ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - ddsd.ddpfPixelFormat.dwRGBBitCount = 16; - ddsd.ddpfPixelFormat.dwRBitMask = 0xF800; - ddsd.ddpfPixelFormat.dwGBitMask = 0x07E0; - ddsd.ddpfPixelFormat.dwBBitMask = 0x001F; + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB; + U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 16; + U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0xF800; + U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x07E0; + U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x001F; hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &cubemap, NULL); ok(hr == DDERR_INVALIDCAPS, "IDirectDraw7::CreateSurface returned %08x\n", hr); @@ -1319,6 +1333,491 @@ static void test_lockrect_invalid(void) } } +static void CompressedTest(void) +{ + HRESULT hr; + IDirectDrawSurface7 *surface; + DDSURFACEDESC2 ddsd, ddsd2; + IDirectDraw7 *dd7 = NULL; + RECT r = { 0, 0, 128, 128 }; + RECT r2 = { 32, 32, 64, 64 }; + + hr = IDirectDraw_QueryInterface(lpDD, &IID_IDirectDraw7, (void **) &dd7); + ok(hr == DD_OK, "IDirectDraw::QueryInterface returned %08x\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS; + ddsd.dwWidth = 128; + ddsd.dwHeight = 128; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY; + U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_FOURCC; + U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1'); + + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL); + ok(hr == DD_OK, "CreateSurface returned %08x\n", hr); + + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2); + ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 8192, "Linear size is %d\n", ddsd2.dwLinearSize); + ok(ddsd2.ddsCaps.dwCaps2 == 0, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2); + IDirectDrawSurface7_Release(surface); + + U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3'); + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL); + ok(hr == DD_OK, "CreateSurface returned %08x\n", hr); + + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2); + ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 16384, "Linear size is %d\n", ddsd2.dwLinearSize); + IDirectDrawSurface7_Release(surface); + + U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5'); + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL); + ok(hr == DD_OK, "CreateSurface returned %08x\n", hr); + + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2); + ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 16384, "Linear size is %d\n", ddsd2.dwLinearSize); + ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface); + + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + + /* Show that the description is not changed when locking the surface. What is really interesting + * about this is that DDSD_LPSURFACE isn't set. + */ + hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0); + ok(hr == DD_OK, "Lock returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 16384, "Linear size is %d\n", ddsd2.dwLinearSize); + ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n"); + + hr = IDirectDrawSurface7_Unlock(surface, NULL); + ok(hr == DD_OK, "Unlock returned %08x\n", hr); + + /* Now what about a locking rect? */ + hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0); + ok(hr == DD_OK, "Lock returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 16384, "Linear size is %d\n", ddsd2.dwLinearSize); + ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n"); + + hr = IDirectDrawSurface7_Unlock(surface, &r); + ok(hr == DD_OK, "Unlock returned %08x\n", hr); + + /* Now what about a different locking offset? */ + hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0); + ok(hr == DD_OK, "Lock returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 16384, "Linear size is %d\n", ddsd2.dwLinearSize); + ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n"); + + hr = IDirectDrawSurface7_Unlock(surface, &r2); + ok(hr == DD_OK, "Unlock returned %08x\n", hr); + IDirectDrawSurface7_Release(surface); + + /* Try this with video memory. A kind of surprise. It still has the LINEARSIZE flag set, + * but seems to have a pitch instead. + */ + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY; + U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1'); + + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL); + ok(hr == DD_OK || hr == DDERR_NOTEXTUREHW, "CreateSurface returned %08x\n", hr); + + /* Not supported everywhere */ + if(SUCCEEDED(hr)) + { + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2); + ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */ + ok(ddsd2.ddsCaps.dwCaps2 == 0, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2); + IDirectDrawSurface7_Release(surface); + + U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3'); + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL); + ok(hr == DD_OK, "CreateSurface returned %08x\n", hr); + + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2); + ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */ + IDirectDrawSurface7_Release(surface); + + U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5'); + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL); + ok(hr == DD_OK, "CreateSurface returned %08x\n", hr); + + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2); + ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */ + ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface); + + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + + /* Show that the description is not changed when locking the surface. What is really interesting + * about this is that DDSD_LPSURFACE isn't set. + */ + hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0); + ok(hr == DD_OK, "Lock returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */ + ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n"); + + hr = IDirectDrawSurface7_Unlock(surface, NULL); + ok(hr == DD_OK, "Unlock returned %08x\n", hr); + + /* Now what about a locking rect? */ + hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0); + ok(hr == DD_OK, "Lock returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */ + ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n"); + + hr = IDirectDrawSurface7_Unlock(surface, &r); + ok(hr == DD_OK, "Unlock returned %08x\n", hr); + + /* Now what about a different locking offset? */ + hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0); + ok(hr == DD_OK, "Lock returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + /* ATI drivers report a broken linear size, thus no need to clone the exact behaviour. nvidia reports the correct size */ + ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n"); + + hr = IDirectDrawSurface7_Unlock(surface, &r2); + ok(hr == DD_OK, "Unlock returned %08x\n", hr); + + IDirectDrawSurface7_Release(surface); + } + else + { + skip("Hardware DXTN textures not supported\n"); + } + + /* What happens to managed textures? Interestingly, Windows reports them as beeing in system + * memory. The linear size fits again. + */ + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; + ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE; + U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','1'); + + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL); + ok(hr == DD_OK || hr == DDERR_NOTEXTUREHW, "CreateSurface returned %08x\n", hr); + + /* Not supported everywhere */ + if(SUCCEEDED(hr)) + { + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2); + ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 8192, "Linear size is %d\n", ddsd2.dwLinearSize); + ok(ddsd2.ddsCaps.dwCaps2 == DDSCAPS2_TEXTUREMANAGE, "Caps2: %08x\n", ddsd2.ddsCaps.dwCaps2); + IDirectDrawSurface7_Release(surface); + + U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','3'); + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL); + ok(hr == DD_OK, "CreateSurface returned %08x\n", hr); + + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2); + ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 16384, "Linear size is %d\n", ddsd2.dwLinearSize); + IDirectDrawSurface7_Release(surface); + + U4(ddsd).ddpfPixelFormat.dwFourCC = MAKEFOURCC('D','X','T','5'); + hr = IDirectDraw7_CreateSurface(dd7, &ddsd, &surface, NULL); + ok(hr == DD_OK, "CreateSurface returned %08x\n", hr); + + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + hr = IDirectDrawSurface7_GetSurfaceDesc(surface, &ddsd2); + ok(hr == DD_OK, "GetSurfaceDesc returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 16384, "Linear size is %d\n", ddsd2.dwLinearSize); + ok(ddsd2.lpSurface == 0, "Surface memory is at %p, expected NULL\n", ddsd2.lpSurface); + + memset(&ddsd2, 0, sizeof(ddsd2)); + ddsd2.dwSize = sizeof(ddsd2); + U4(ddsd2).ddpfPixelFormat.dwSize = sizeof(U4(ddsd2).ddpfPixelFormat); + + /* Show that the description is not changed when locking the surface. What is really interesting + * about this is that DDSD_LPSURFACE isn't set. + */ + hr = IDirectDrawSurface7_Lock(surface, NULL, &ddsd2, DDLOCK_READONLY, 0); + ok(hr == DD_OK, "Lock returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 16384, "Linear size is %d\n", ddsd2.dwLinearSize); + ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n"); + + hr = IDirectDrawSurface7_Unlock(surface, NULL); + ok(hr == DD_OK, "Unlock returned %08x\n", hr); + + /* Now what about a locking rect? */ + hr = IDirectDrawSurface7_Lock(surface, &r, &ddsd2, DDLOCK_READONLY, 0); + ok(hr == DD_OK, "Lock returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 16384, "\"Linear\" size is %d\n", ddsd2.dwLinearSize); + ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n"); + + hr = IDirectDrawSurface7_Unlock(surface, &r); + ok(hr == DD_OK, "Unlock returned %08x\n", hr); + + /* Now what about a different locking offset? */ + hr = IDirectDrawSurface7_Lock(surface, &r2, &ddsd2, DDLOCK_READONLY, 0); + ok(hr == DD_OK, "Lock returned %08x\n", hr); + + ok(ddsd2.dwFlags == (DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_LINEARSIZE), + "Surface desc flags: %08x\n", ddsd2.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwFlags == DDPF_FOURCC, "Pixel format flags: %08x\n", U4(ddsd2).ddpfPixelFormat.dwFlags); + ok(U4(ddsd2).ddpfPixelFormat.dwRGBBitCount == 0, "RGB bitcount: %08x\n", U4(ddsd2).ddpfPixelFormat.dwRGBBitCount); + ok(ddsd2.ddsCaps.dwCaps == (DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY), + "Surface caps flags: %08x\n", ddsd2.ddsCaps.dwCaps); + ok(ddsd2.dwLinearSize == 16384, "\"Linear\" size is %d\n", ddsd2.dwLinearSize); + ok(ddsd2.lpSurface != 0, "Surface memory is at NULL\n"); + + hr = IDirectDrawSurface7_Unlock(surface, &r2); + ok(hr == DD_OK, "Unlock returned %08x\n", hr); + + IDirectDrawSurface7_Release(surface); + } + else + { + skip("Hardware DXTN textures not supported\n"); + } + + IDirectDraw7_Release(dd7); +} + +static void SizeTest(void) +{ + LPDIRECTDRAWSURFACE dsurface = NULL; + DDSURFACEDESC desc; + HRESULT ret; + HWND window = CreateWindow( "static", "ddraw_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL ); + + /* Create an offscreen surface surface without a size */ + ZeroMemory(&desc, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS; + desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; + ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL); + ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without a size info returned %08x\n", ret); + if(dsurface) + { + trace("Surface at %p\n", dsurface); + IDirectDrawSurface_Release(dsurface); + dsurface = NULL; + } + + /* Create an offscreen surface surface with only a width parameter */ + ZeroMemory(&desc, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS | DDSD_WIDTH; + desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; + desc.dwWidth = 128; + ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL); + ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without hight info returned %08x\n", ret); + if(dsurface) + { + IDirectDrawSurface_Release(dsurface); + dsurface = NULL; + } + + /* Create an offscreen surface surface with only a height parameter */ + ZeroMemory(&desc, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT; + desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; + desc.dwHeight = 128; + ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL); + ok(ret == DDERR_INVALIDPARAMS, "Creating an offscreen plain surface without width info returned %08x\n", ret); + if(dsurface) + { + IDirectDrawSurface_Release(dsurface); + dsurface = NULL; + } + + /* Sanity check */ + ZeroMemory(&desc, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; + desc.dwHeight = 128; + desc.dwWidth = 128; + ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL); + ok(ret == DD_OK, "Creating an offscreen plain surface with width and height info returned %08x\n", ret); + if(dsurface) + { + IDirectDrawSurface_Release(dsurface); + dsurface = NULL; + } + + /* Test a primary surface size */ + ret = IDirectDraw_SetCooperativeLevel(lpDD, window, DDSCL_NORMAL); + ok(ret == DD_OK, "SetCooperativeLevel failed with %08x\n", ret); + + ZeroMemory(&desc, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS; + desc.ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE; + desc.dwHeight = 128; /* Keep them set to check what happens */ + desc.dwWidth = 128; /* Keep them set to check what happens */ + ret = IDirectDraw_CreateSurface(lpDD, &desc, &dsurface, NULL); + ok(ret == DD_OK, "Creating a primary surface without width and height info returned %08x\n", ret); + if(dsurface) + { + ret = IDirectDrawSurface_GetSurfaceDesc(dsurface, &desc); + ok(ret == DD_OK, "GetSurfaceDesc returned %x\n", ret); + + IDirectDrawSurface_Release(dsurface); + dsurface = NULL; + + ok(desc.dwFlags & DDSD_WIDTH, "Primary surface doesn't have width set\n"); + ok(desc.dwFlags & DDSD_HEIGHT, "Primary surface doesn't have height set\n"); + ok(desc.dwWidth == GetSystemMetrics(SM_CXSCREEN), "Surface width differs from screen width\n"); + ok(desc.dwHeight == GetSystemMetrics(SM_CYSCREEN), "Surface height differs from screen height\n"); + } + ret = IDirectDraw_SetCooperativeLevel(lpDD, NULL, DDSCL_NORMAL); + ok(ret == DD_OK, "SetCooperativeLevel failed with %08x\n", ret); +} + START_TEST(dsurface) { if (!CreateDirectDraw()) @@ -1334,5 +1833,7 @@ START_TEST(dsurface) AttachmentTest(); CubeMapTest(); test_lockrect_invalid(); + CompressedTest(); + SizeTest(); ReleaseDirectDraw(); } diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c index 7b9ef6d9bf9..86e13080e13 100644 --- a/dlls/gdi32/dib.c +++ b/dlls/gdi32/dib.c @@ -364,6 +364,8 @@ INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx, INT ret; DC *dc; + if (!bits) return 0; + if (!(dc = DC_GetDCUpdate( hdc ))) return 0; if(dc->funcs->pSetDIBitsToDevice) diff --git a/dlls/imagehlp/access.c b/dlls/imagehlp/access.c index 1560d115a65..2aeedff52fb 100644 --- a/dlls/imagehlp/access.c +++ b/dlls/imagehlp/access.c @@ -23,7 +23,6 @@ #include "windef.h" #include "winbase.h" #include "winnt.h" -#include "winreg.h" #include "winternl.h" #include "winerror.h" #include "wine/debug.h" diff --git a/dlls/imagehlp/imagehlp_main.c b/dlls/imagehlp/imagehlp_main.c index 42a1a410872..91c76bdb7d4 100644 --- a/dlls/imagehlp/imagehlp_main.c +++ b/dlls/imagehlp/imagehlp_main.c @@ -23,7 +23,6 @@ #include "windef.h" #include "winbase.h" #include "imagehlp.h" -#include "winerror.h" #include "wine/debug.h" /**********************************************************************/ diff --git a/dlls/imagehlp/integrity.c b/dlls/imagehlp/integrity.c index 99608b70a72..fb228f49ba9 100644 --- a/dlls/imagehlp/integrity.c +++ b/dlls/imagehlp/integrity.c @@ -24,7 +24,6 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" -#include "winreg.h" #include "winternl.h" #include "winnt.h" #include "imagehlp.h" diff --git a/dlls/imagehlp/modify.c b/dlls/imagehlp/modify.c index 47aa44cbbb3..668069ba9e6 100644 --- a/dlls/imagehlp/modify.c +++ b/dlls/imagehlp/modify.c @@ -22,7 +22,6 @@ #include "windef.h" #include "winbase.h" -#include "winreg.h" #include "winternl.h" #include "winerror.h" #include "wine/debug.h" diff --git a/dlls/infosoft/wordbreaker.c b/dlls/infosoft/wordbreaker.c index f65665369eb..514f868d95e 100644 --- a/dlls/infosoft/wordbreaker.c +++ b/dlls/infosoft/wordbreaker.c @@ -27,7 +27,6 @@ #include "windef.h" #include "winbase.h" #include "winuser.h" -#include "winreg.h" #include "ole2.h" #include "indexsrv.h" #include "wine/unicode.h" diff --git a/dlls/inseng/inseng_main.c b/dlls/inseng/inseng_main.c index 83b145796c7..8ceb252b511 100644 --- a/dlls/inseng/inseng_main.c +++ b/dlls/inseng/inseng_main.c @@ -27,7 +27,6 @@ #include "windef.h" #include "winbase.h" #include "winuser.h" -#include "winreg.h" #include "ole2.h" #include "initguid.h" diff --git a/dlls/itss/itss.c b/dlls/itss/itss.c index cca4f61df72..711d116054b 100644 --- a/dlls/itss/itss.c +++ b/dlls/itss/itss.c @@ -31,13 +31,10 @@ #include "windef.h" #include "winbase.h" #include "winuser.h" -#include "winnls.h" #include "winreg.h" #include "ole2.h" #include "advpub.h" -#include "uuids.h" - #include "wine/unicode.h" #include "wine/debug.h" diff --git a/dlls/itss/moniker.c b/dlls/itss/moniker.c index 370a23fda71..d57f38167b6 100644 --- a/dlls/itss/moniker.c +++ b/dlls/itss/moniker.c @@ -30,12 +30,8 @@ #include "windef.h" #include "winbase.h" #include "winuser.h" -#include "winnls.h" -#include "winreg.h" #include "ole2.h" -#include "uuids.h" - #include "wine/itss.h" #include "wine/unicode.h" #include "wine/debug.h" diff --git a/dlls/itss/storage.c b/dlls/itss/storage.c index 4163605b559..97d7755826a 100644 --- a/dlls/itss/storage.c +++ b/dlls/itss/storage.c @@ -30,12 +30,8 @@ #include "windef.h" #include "winbase.h" #include "winuser.h" -#include "winnls.h" -#include "winreg.h" #include "ole2.h" -#include "uuids.h" - #include "chm_lib.h" #include "itsstor.h" diff --git a/dlls/kernel32/Makefile.in b/dlls/kernel32/Makefile.in index 09105be6615..7b0b4ccf919 100644 --- a/dlls/kernel32/Makefile.in +++ b/dlls/kernel32/Makefile.in @@ -7,6 +7,7 @@ MODULE = kernel32.dll IMPORTLIB = libkernel32.$(IMPLIBEXT) IMPORTS = ntdll EXTRALIBS = @COREFOUNDATIONLIB@ @LIBPOLL@ +DLLFILENAME = KERNEL32.dll BASEADDRESS = 0x7b800000 SPEC_SRCS16 = \ diff --git a/dlls/kernel32/actctx.c b/dlls/kernel32/actctx.c index a0bd3c1bfa7..bdb6a1a54fb 100644 --- a/dlls/kernel32/actctx.c +++ b/dlls/kernel32/actctx.c @@ -25,7 +25,6 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" -#include "winnls.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(actctx); diff --git a/dlls/kernel32/atom.c b/dlls/kernel32/atom.c index f444ae0a9d8..d6caec25494 100644 --- a/dlls/kernel32/atom.c +++ b/dlls/kernel32/atom.c @@ -30,11 +30,9 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" -#include "winreg.h" #include "winternl.h" #include "wine/exception.h" -#include "excpt.h" #include "wine/unicode.h" #include "kernel_private.h" diff --git a/dlls/kernel32/atom16.c b/dlls/kernel32/atom16.c index c43fb83b432..0c52f1f7308 100644 --- a/dlls/kernel32/atom16.c +++ b/dlls/kernel32/atom16.c @@ -41,7 +41,6 @@ #include "wine/unicode.h" #include "wine/winbase16.h" -#include "kernel_private.h" #include "kernel16_private.h" #include "wine/debug.h" diff --git a/dlls/kernel32/computername.c b/dlls/kernel32/computername.c index d2c0a7cebc2..5e811f87551 100644 --- a/dlls/kernel32/computername.c +++ b/dlls/kernel32/computername.c @@ -43,7 +43,6 @@ #include "winternl.h" #include "wine/unicode.h" #include "wine/exception.h" -#include "excpt.h" #include "wine/debug.h" #include "kernel_private.h" diff --git a/dlls/kernel32/cpu.c b/dlls/kernel32/cpu.c index 27a50aed006..7567af5181e 100644 --- a/dlls/kernel32/cpu.c +++ b/dlls/kernel32/cpu.c @@ -51,7 +51,6 @@ #include "winbase.h" #include "winnt.h" #include "winternl.h" -#include "winerror.h" #include "wine/unicode.h" #include "wine/debug.h" diff --git a/dlls/kernel32/error16.c b/dlls/kernel32/error16.c index d7a1e35e6da..ce8935d3974 100644 --- a/dlls/kernel32/error16.c +++ b/dlls/kernel32/error16.c @@ -24,7 +24,6 @@ #include #include "windef.h" -#include "winbase.h" #include "wine/winbase16.h" #include "wine/debug.h" diff --git a/dlls/kernel32/except.c b/dlls/kernel32/except.c index fb2a5d5d400..32305cb4bf5 100644 --- a/dlls/kernel32/except.c +++ b/dlls/kernel32/except.c @@ -44,7 +44,6 @@ #define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" -#include "winerror.h" #include "winternl.h" #include "wingdi.h" #include "winuser.h" diff --git a/dlls/kernel32/file.c b/dlls/kernel32/file.c index 6b2fb4939ae..b3cf323df60 100644 --- a/dlls/kernel32/file.c +++ b/dlls/kernel32/file.c @@ -43,7 +43,6 @@ #include "kernel_private.h" #include "wine/exception.h" -#include "excpt.h" #include "wine/unicode.h" #include "wine/debug.h" #include "thread.h" diff --git a/dlls/kernel32/global16.c b/dlls/kernel32/global16.c index 91d739caa4b..203152562dc 100644 --- a/dlls/kernel32/global16.c +++ b/dlls/kernel32/global16.c @@ -43,7 +43,6 @@ #include "kernel_private.h" #include "kernel16_private.h" #include "wine/debug.h" -#include "winerror.h" WINE_DEFAULT_DEBUG_CHANNEL(global); diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c index 610cff08388..98552ca18ae 100644 --- a/dlls/kernel32/heap.c +++ b/dlls/kernel32/heap.c @@ -60,7 +60,6 @@ #include "winerror.h" #include "winnt.h" #include "winternl.h" -#include "excpt.h" #include "wine/exception.h" #include "wine/debug.h" diff --git a/dlls/kernel32/instr.c b/dlls/kernel32/instr.c index a7e60f19de5..8a37a47b864 100644 --- a/dlls/kernel32/instr.c +++ b/dlls/kernel32/instr.c @@ -27,7 +27,6 @@ #include "windef.h" #include "winbase.h" -#include "wingdi.h" #include "wine/winuser16.h" #include "excpt.h" #include "thread.h" diff --git a/dlls/kernel32/kernel_main.c b/dlls/kernel32/kernel_main.c index 9f6b3114687..5e72ceed400 100644 --- a/dlls/kernel32/kernel_main.c +++ b/dlls/kernel32/kernel_main.c @@ -40,6 +40,9 @@ #include "kernel_private.h" #include "kernel16_private.h" #include "console_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(process); extern int __wine_set_signal_handler(unsigned, int (*)(unsigned)); @@ -69,9 +72,44 @@ static void thread_detach(void) /*********************************************************************** + * set_entry_point + */ +static void set_entry_point( HMODULE module, const char *name, DWORD rva ) +{ + IMAGE_EXPORT_DIRECTORY *exports; + DWORD exp_size; + + if ((exports = RtlImageDirectoryEntryToData( module, TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size ))) + { + DWORD *functions = (DWORD *)((char *)module + exports->AddressOfFunctions); + const WORD *ordinals = (const WORD *)((const char *)module + exports->AddressOfNameOrdinals); + const DWORD *names = (const DWORD *)((const char *)module + exports->AddressOfNames); + int min = 0, max = exports->NumberOfNames - 1; + + while (min <= max) + { + int res, pos = (min + max) / 2; + const char *ename = (const char *)module + names[pos]; + if (!(res = strcmp( ename, name ))) + { + WORD ordinal = ordinals[pos]; + assert( ordinal < exports->NumberOfFunctions ); + TRACE( "setting %s at %p to %08x\n", name, &functions[ordinal], rva ); + functions[ordinal] = rva; + return; + } + if (res > 0) max = pos - 1; + else min = pos + 1; + } + } +} + + +/*********************************************************************** * KERNEL process initialisation routine */ -static BOOL process_attach(void) +static BOOL process_attach( HMODULE module ) { SYSTEM_INFO si; RTL_USER_PROCESS_PARAMETERS *params = NtCurrentTeb()->Peb->ProcessParameters; @@ -108,8 +146,13 @@ static BOOL process_attach(void) /* copy process information from ntdll */ ENV_CopyStartupInformation(); + if (!(GetVersion() & 0x80000000)) + { + /* Securom checks for this one when version is NT */ + set_entry_point( module, "FT_Thunk", 0 ); + } #ifdef __i386__ - if (GetVersion() & 0x80000000) + else { /* create the shared heap for broken win95 native dlls */ HeapCreate( HEAP_SHARED, 0, 0 ); @@ -148,7 +191,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) switch(reason) { case DLL_PROCESS_ATTACH: - return process_attach(); + return process_attach( hinst ); case DLL_THREAD_ATTACH: thread_attach(); break; diff --git a/dlls/kernel32/ne_module.c b/dlls/kernel32/ne_module.c index 9e464e4dc8a..93f8f8edd78 100644 --- a/dlls/kernel32/ne_module.c +++ b/dlls/kernel32/ne_module.c @@ -37,7 +37,6 @@ #include "wownt32.h" #include "winternl.h" #include "toolhelp.h" -#include "excpt.h" #include "kernel_private.h" #include "kernel16_private.h" #include "wine/exception.h" diff --git a/dlls/kernel32/oldconfig.c b/dlls/kernel32/oldconfig.c index cf892e832da..09e407b59d5 100644 --- a/dlls/kernel32/oldconfig.c +++ b/dlls/kernel32/oldconfig.c @@ -44,9 +44,7 @@ #define NONAMELESSSTRUCT #include "windef.h" #include "winbase.h" -#include "winnls.h" #include "winternl.h" -#include "winioctl.h" #include "ntddscsi.h" #include "wine/library.h" #include "wine/unicode.h" diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 8e5999fb267..036730fa5b6 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -45,7 +45,6 @@ #define WIN32_NO_STATUS #include "wine/winbase16.h" #include "wine/winuser16.h" -#include "winioctl.h" #include "winternl.h" #include "kernel_private.h" #include "wine/exception.h" diff --git a/dlls/kernel32/resource.c b/dlls/kernel32/resource.c index 2b1bdf415d2..66e8adcc8f7 100644 --- a/dlls/kernel32/resource.c +++ b/dlls/kernel32/resource.c @@ -32,10 +32,8 @@ #include "windef.h" #include "winbase.h" #include "winternl.h" -#include "wownt32.h" #include "wine/winbase16.h" #include "wine/debug.h" -#include "excpt.h" #include "wine/exception.h" #include "wine/unicode.h" #include "wine/list.h" diff --git a/dlls/kernel32/selector.c b/dlls/kernel32/selector.c index 53ad5b42c22..db3a47e8fb9 100644 --- a/dlls/kernel32/selector.c +++ b/dlls/kernel32/selector.c @@ -23,7 +23,6 @@ #include -#include "winerror.h" #include "wine/winbase16.h" #include "wine/server.h" #include "wine/debug.h" diff --git a/dlls/kernel32/stress.c b/dlls/kernel32/stress.c index c722631a365..c97a1b250c1 100644 --- a/dlls/kernel32/stress.c +++ b/dlls/kernel32/stress.c @@ -19,7 +19,6 @@ #include #include "windef.h" -#include "winbase.h" #include "wine/windef16.h" #include "wine/debug.h" diff --git a/dlls/kernel32/string.c b/dlls/kernel32/string.c index 6201d2fa719..ecac281f133 100644 --- a/dlls/kernel32/string.c +++ b/dlls/kernel32/string.c @@ -30,7 +30,6 @@ #define WINE_NO_INLINE_STRING #include "windef.h" #include "winbase.h" -#include "excpt.h" #include "wine/winbase16.h" #include "wine/unicode.h" #include "wine/exception.h" diff --git a/dlls/kernel32/system.c b/dlls/kernel32/system.c index d0b79634fcc..ab38467a19f 100644 --- a/dlls/kernel32/system.c +++ b/dlls/kernel32/system.c @@ -24,7 +24,6 @@ #include "windef.h" #include "winbase.h" -#include "wingdi.h" #include "wine/winbase16.h" #include "wine/winuser16.h" #include "wownt32.h" diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c index cdbe1e129f2..59cbfdf130d 100644 --- a/dlls/kernel32/thread.c +++ b/dlls/kernel32/thread.c @@ -34,7 +34,6 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" -#include "winnls.h" #include "thread.h" #include "wine/winbase16.h" #include "wine/exception.h" diff --git a/dlls/kernel32/toolhelp16.c b/dlls/kernel32/toolhelp16.c index fdb611f55b9..c6931d28e36 100644 --- a/dlls/kernel32/toolhelp16.c +++ b/dlls/kernel32/toolhelp16.c @@ -31,7 +31,6 @@ #include "windef.h" #include "winbase.h" #include "winternl.h" -#include "winerror.h" #include "wine/winbase16.h" #include "toolhelp.h" diff --git a/dlls/kernel32/virtual.c b/dlls/kernel32/virtual.c index d2b473e2ca6..9bb13f123ac 100644 --- a/dlls/kernel32/virtual.c +++ b/dlls/kernel32/virtual.c @@ -40,7 +40,6 @@ #include "winternl.h" #include "winerror.h" #include "wine/exception.h" -#include "excpt.h" #include "wine/debug.h" #include "kernel_private.h" diff --git a/dlls/kernel32/volume.c b/dlls/kernel32/volume.c index 536fcfac372..0f4c5da46f7 100644 --- a/dlls/kernel32/volume.c +++ b/dlls/kernel32/volume.c @@ -36,7 +36,6 @@ #include "winnls.h" #include "winternl.h" #include "winioctl.h" -#include "ntddstor.h" #include "ntddcdrm.h" #include "kernel_private.h" #include "wine/library.h" diff --git a/dlls/kernel32/windebug.c b/dlls/kernel32/windebug.c index 665508daf26..7b913b253dc 100644 --- a/dlls/kernel32/windebug.c +++ b/dlls/kernel32/windebug.c @@ -22,7 +22,6 @@ #include #include #include "windef.h" -#include "winbase.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(dll); diff --git a/dlls/localui/localui.c b/dlls/localui/localui.c index 05950e3ffac..2acfc7ecafa 100644 --- a/dlls/localui/localui.c +++ b/dlls/localui/localui.c @@ -42,15 +42,22 @@ WINE_DEFAULT_DEBUG_CHANNEL(localui); static HINSTANCE LOCALUI_hInstance; static const WCHAR cmd_AddPortW[] = {'A','d','d','P','o','r','t',0}; +static const WCHAR cmd_ConfigureLPTPortCommandOKW[] = {'C','o','n','f','i','g','u','r','e', + 'L','P','T','P','o','r','t', + 'C','o','m','m','a','n','d','O','K',0}; static const WCHAR cmd_DeletePortW[] = {'D','e','l','e','t','e','P','o','r','t',0}; static const WCHAR cmd_GetDefaultCommConfigW[] = {'G','e','t', 'D','e','f','a','u','l','t', 'C','o','m','m','C','o','n','f','i','g',0}; +static const WCHAR cmd_GetTransmissionRetryTimeoutW[] = {'G','e','t', + 'T','r','a','n','s','m','i','s','s','i','o','n', + 'R','e','t','r','y','T','i','m','e','o','u','t',0}; static const WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0}; static const WCHAR cmd_SetDefaultCommConfigW[] = {'S','e','t', 'D','e','f','a','u','l','t', 'C','o','m','m','C','o','n','f','i','g',0}; +static const WCHAR fmt_uW[] = {'%','u',0}; static const WCHAR portname_LPT[] = {'L','P','T',0}; static const WCHAR portname_COM[] = {'C','O','M',0}; static const WCHAR portname_FILE[] = {'F','I','L','E',':',0}; @@ -67,6 +74,14 @@ typedef struct tag_addportui_t { HANDLE hXcv; } addportui_t; +typedef struct tag_lptconfig_t { + HANDLE hXcv; + DWORD value; +} lptconfig_t; + + +static INT_PTR CALLBACK dlgproc_lptconfig(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + /***************************************************** * strdupWW [internal] */ @@ -131,6 +146,29 @@ static BOOL dlg_configure_com(HANDLE hXcv, HWND hWnd, PCWSTR pPortName) return FALSE; } + +/***************************************************** + * dlg_configure_lpt [internal] + * + */ + +static BOOL dlg_configure_lpt(HANDLE hXcv, HWND hWnd) +{ + lptconfig_t data; + BOOL res; + + + data.hXcv = hXcv; + + res = DialogBoxParamW(LOCALUI_hInstance, MAKEINTRESOURCEW(LPTCONFIG_DIALOG), hWnd, + dlgproc_lptconfig, (LPARAM) &data); + + TRACE("got %u with %u\n", res, GetLastError()); + + if (!res) SetLastError(ERROR_CANCELLED); + return res; +} + /****************************************************************** * dlg_port_already_exists [internal] */ @@ -291,6 +329,86 @@ static INT_PTR CALLBACK dlgproc_addport(HWND hwnd, UINT msg, WPARAM wparam, LPAR return FALSE; } +/***************************************************************************** + * dlgproc_lptconfig [internal] + * + * Our message-proc is simple, as the range-check is done only during the + * command "OK" and the dialog is set to the start-value at "out of range". + * + * Native localui.dll does the check during keyboard-input and set the dialog + * to the previous value. + * + */ + +static INT_PTR CALLBACK dlgproc_lptconfig(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + lptconfig_t * data; + WCHAR bufferW[16]; + DWORD status; + DWORD dummy; + DWORD len; + DWORD res; + + + switch(msg) + { + case WM_INITDIALOG: + SetWindowLongPtrW(hwnd, DWLP_USER, lparam); + data = (lptconfig_t *) lparam; + + /* Get current setting */ + data->value = 45; + status = ERROR_SUCCESS; + res = XcvDataW( data->hXcv, cmd_GetTransmissionRetryTimeoutW, + (PBYTE) &dummy, 0, + (PBYTE) &data->value, sizeof(data->value), &len, &status); + + TRACE("got %u with status %u\n", res, status); + + /* Set current setting as the initial value in the Dialog */ + SetDlgItemInt(hwnd, LPTCONFIG_EDIT, data->value, FALSE); + return TRUE; + + case WM_COMMAND: + if (wparam == MAKEWPARAM(IDOK, BN_CLICKED)) + { + data = (lptconfig_t *) GetWindowLongPtrW(hwnd, DWLP_USER); + + status = FALSE; + res = GetDlgItemInt(hwnd, LPTCONFIG_EDIT, (BOOL *) &status, FALSE); + /* length is in WCHAR, including the '\0' */ + GetDlgItemTextW(hwnd, LPTCONFIG_EDIT, bufferW, sizeof(bufferW) / sizeof(bufferW[0])); + TRACE("got %s and %u (translated: %u)\n", debugstr_w(bufferW), res, status); + + /* native localui.dll use the same limits */ + if ((res > 0) && (res < 1000000) && status) { + sprintfW(bufferW, fmt_uW, res); + res = XcvDataW( data->hXcv, cmd_ConfigureLPTPortCommandOKW, + (PBYTE) bufferW, + (lstrlenW(bufferW) +1) * sizeof(WCHAR), + (PBYTE) &dummy, 0, &len, &status); + + TRACE("got %u with status %u\n", res, status); + EndDialog(hwnd, TRUE); + return TRUE; + } + + /* Set initial value and rerun the Dialog */ + SetDlgItemInt(hwnd, LPTCONFIG_EDIT, data->value, FALSE); + return TRUE; + } + + if (wparam == MAKEWPARAM(IDCANCEL, BN_CLICKED)) + { + EndDialog(hwnd, FALSE); + return TRUE; + } + return FALSE; + } + return FALSE; +} + + /***************************************************** * get_type_from_name (internal) * @@ -471,6 +589,10 @@ static BOOL WINAPI localui_ConfigurePortUI(PCWSTR pName, HWND hWnd, PCWSTR pPort res = dlg_configure_com(hXcv, hWnd, pPortName); break; + case PORT_IS_LPT: + res = dlg_configure_lpt(hXcv, hWnd); + break; + default: dlg_nothingtoconfig(hWnd); SetLastError(ERROR_CANCELLED); @@ -567,9 +689,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) switch(fdwReason) { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ - case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls( hinstDLL ); LOCALUI_hInstance = hinstDLL; diff --git a/dlls/localui/localui.h b/dlls/localui/localui.h index 599ef582910..aa244bdc824 100644 --- a/dlls/localui/localui.h +++ b/dlls/localui/localui.h @@ -24,7 +24,11 @@ /* ## Resource-ID ## */ #define ADDPORT_DIALOG 100 -#define ADDPORT_EDIT 201 +#define ADDPORT_EDIT 101 + +#define LPTCONFIG_DIALOG 200 +#define LPTCONFIG_GROUP 201 +#define LPTCONFIG_EDIT 202 #define IDS_LOCALPORT 300 #define IDS_INVALIDNAME 301 diff --git a/dlls/localui/localui.rc b/dlls/localui/localui.rc index ff242096bf5..4841708fc4a 100644 --- a/dlls/localui/localui.rc +++ b/dlls/localui/localui.rc @@ -38,4 +38,5 @@ #include "wine/wine_common_ver.rc" +#include "ui_De.rc" #include "ui_En.rc" diff --git a/dlls/localui/ui_De.rc b/dlls/localui/ui_De.rc new file mode 100644 index 00000000000..5e82f22da5a --- /dev/null +++ b/dlls/localui/ui_De.rc @@ -0,0 +1,54 @@ +/* + * German resources for localui + * + * Copyright 2007 Detlef Riekenberg + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_GERMAN, SUBLANG_DEFAULT + +ADDPORT_DIALOG DIALOG LOADONCALL MOVEABLE DISCARDABLE 6, 18, 245, 47 +STYLE DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFONT | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Lokalen Anschluss hinzufügen" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Lokaler Anschuss, der hinzugefügt werden soll:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Abbrechen", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOG LOADONCALL MOVEABLE DISCARDABLE 6, 18, 220, 47 +STYLE DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFONT | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "LPT-Anschluss konfigurieren" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Zeitüberschreitung (Sekunden)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "Ãœ&bertragung wiederholen:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Abbrechen", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END + + +STRINGTABLE DISCARDABLE +{ + IDS_LOCALPORT "Lokaler Anschluss" + IDS_INVALIDNAME "'%s' ist kein gültiger Anschlussname" + IDS_PORTEXISTS "Der Anschluss %s existiert bereits" + IDS_NOTHINGTOCONFIG "Dieser Anschluss hat keine Optionen zum Konfigurieren" +} diff --git a/dlls/localui/ui_En.rc b/dlls/localui/ui_En.rc index 8a1e5b9c8cf..c2de6263a8a 100644 --- a/dlls/localui/ui_En.rc +++ b/dlls/localui/ui_En.rc @@ -32,6 +32,19 @@ BEGIN END +LPTCONFIG_DIALOG DIALOG LOADONCALL MOVEABLE DISCARDABLE 6, 18, 220, 47 +STYLE DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFONT | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Configure LPT Port" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Timeout (seconds)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Transmission Retry:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Cancel", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END + + STRINGTABLE DISCARDABLE { IDS_LOCALPORT "Local Port" diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index 17d22a09cd3..452be8b5702 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -165,80 +165,6 @@ static BOOL load_xpcom(PRUnichar *gre_path) return TRUE; } -static BOOL load_mozilla(PRUnichar *gre_path) -{ - DWORD res, type, i, size = MAX_PATH; - HKEY mozilla_key, hkey; - WCHAR key_name[100]; - BOOL ret = FALSE; - - static const WCHAR wszGreKey[] = - {'S','o','f','t','w','a','r','e','\\', - 'm','o','z','i','l','l','a','.','o','r','g','\\', - 'G','R','E',0}; - - static const WCHAR wszGreHome[] = {'G','r','e','H','o','m','e',0}; - - res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszGreKey, &mozilla_key); - if(res != ERROR_SUCCESS) { - TRACE("Could not open key %s\n", debugstr_w(wszGreKey)); - return FALSE; - } - - for(i=0; !ret && RegEnumKeyW(mozilla_key, i, key_name, sizeof(key_name)/sizeof(WCHAR)) == ERROR_SUCCESS; i++) { - RegOpenKeyW(mozilla_key, key_name, &hkey); - res = RegQueryValueExW(hkey, wszGreHome, NULL, &type, (LPBYTE)gre_path, &size); - if(res == ERROR_SUCCESS) - ret = TRUE; - RegCloseKey(hkey); - } - - RegCloseKey(mozilla_key); - return ret ? load_xpcom(gre_path) : FALSE; -} - -static BOOL load_mozctl(PRUnichar *gre_path) -{ - HKEY hkey; - DWORD res, type, size = MAX_PATH; - - static const WCHAR wszMozCtlKey[] = - {'S','o','f','t','w','a','r','e','\\','M','o','z','i','l','l','a',0}; - static const WCHAR wszBinDirectoryPath[] = - {'B','i','n','D','i','r','e','c','t','o','r','y','P','a','t','h',0}; - static const WCHAR wszMozCtlClsidKey[] = - {'C','L','S','I','D','\\', - '{','1','3','3','9','B','5','4','C','-','3','4','5','3','-','1','1','D','2', - '-','9','3','B','9','-','0','0','0','0','0','0','0','0','0','0','0','0','}','\\', - 'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0}; - - res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszMozCtlKey, &hkey); - if(res == ERROR_SUCCESS) { - res = RegQueryValueExW(hkey, wszBinDirectoryPath, NULL, &type, (LPBYTE)gre_path, &size); - if(res == ERROR_SUCCESS) - return load_xpcom(gre_path); - else - ERR("Could not get value %s\n", debugstr_w(wszBinDirectoryPath)); - } - - res = RegOpenKeyW(HKEY_CLASSES_ROOT, wszMozCtlClsidKey, &hkey); - if(res == ERROR_SUCCESS) { - res = RegQueryValueExW(hkey, NULL, NULL, &type, (LPBYTE)gre_path, &size); - if(res == ERROR_SUCCESS) { - WCHAR *ptr; - if((ptr = strrchrW(gre_path, '\\'))) - ptr[1] = 0; - return load_xpcom(gre_path); - }else { - ERR("Could not get value of %s\n", debugstr_w(wszMozCtlClsidKey)); - } - } - - TRACE("Could not find Mozilla ActiveX Control\n"); - - return FALSE; -} - static void check_version(LPCWSTR gre_path) { WCHAR file_name[MAX_PATH]; @@ -419,8 +345,6 @@ static BOOL load_gecko(void) loading_thread = GetCurrentThreadId(); if(load_wine_gecko(gre_path) - || load_mozctl(gre_path) - || load_mozilla(gre_path) || (install_wine_gecko() && load_wine_gecko(gre_path))) ret = init_xpcom(gre_path); else diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 8ff889b061f..689f9c42b70 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -4719,29 +4719,113 @@ static UINT ACTION_UnregisterComPlus( MSIPACKAGE *package ) return msi_unimplemented_action_stub( package, "UnregisterComPlus", table ); } +static UINT ACTION_InstallSFPCatalogFile( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'S','F','P','C','a','t','a','l','o','g',0 }; + return msi_unimplemented_action_stub( package, "InstallSFPCatalogFile", table ); +} + +static UINT ACTION_RemoveDuplicateFiles( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'D','u','p','l','i','c','a','t','e','F','i','l','e',0 }; + return msi_unimplemented_action_stub( package, "RemoveDuplicateFiles", table ); +} + +static UINT ACTION_RemoveExistingProducts( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'U','p','g','r','a','d','e',0 }; + return msi_unimplemented_action_stub( package, "RemoveExistingProducts", table ); +} + +static UINT ACTION_RemoveFolders( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'C','r','e','a','t','e','F','o','l','d','e','r',0 }; + return msi_unimplemented_action_stub( package, "RemoveFolders", table ); +} + +static UINT ACTION_RemoveODBC( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'O','D','B','C','D','r','i','v','e','r',0 }; + return msi_unimplemented_action_stub( package, "RemoveODBC", table ); +} + +static UINT ACTION_RemoveRegistryValues( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'R','e','m','o','v','e','R','e','g','i','s','t','r','y',0 }; + return msi_unimplemented_action_stub( package, "RemoveRegistryValues", table ); +} + +static UINT ACTION_RemoveShortcuts( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'S','h','o','r','t','c','u','t',0 }; + return msi_unimplemented_action_stub( package, "RemoveShortcuts", table ); +} + +static UINT ACTION_UnpublishComponents( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'P','u','b','l','i','s','h','C','o','m','p','o','n','e','n','t',0 }; + return msi_unimplemented_action_stub( package, "UnpublishComponents", table ); +} + +static UINT ACTION_UnpublishFeatures( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'F','e','a','t','u','r','e','C','o','m','p','o','n','e','n','t','s',0 }; + return msi_unimplemented_action_stub( package, "UnpublishFeatures", table ); +} + +static UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'A','p','p','I','d',0 }; + return msi_unimplemented_action_stub( package, "UnregisterClassInfo", table ); +} + +static UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'E','x','t','e','n','s','i','o','n',0 }; + return msi_unimplemented_action_stub( package, "UnregisterExtensionInfo", table ); +} + +static UINT ACTION_UnregisterMIMEInfo( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'M','I','M','E',0 }; + return msi_unimplemented_action_stub( package, "UnregisterMIMEInfo", table ); +} + +static UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'P','r','o','g','I','d',0 }; + return msi_unimplemented_action_stub( package, "UnregisterProgIdInfo", table ); +} + +static UINT ACTION_UnregisterTypeLibraries( MSIPACKAGE *package ) +{ + static const WCHAR table[] = { 'T','y','p','e','L','i','b',0 }; + return msi_unimplemented_action_stub( package, "UnregisterTypeLibraries", table ); +} + static const struct _actions StandardActions[] = { { szAllocateRegistrySpace, ACTION_AllocateRegistrySpace }, { szAppSearch, ACTION_AppSearch }, { szBindImage, ACTION_BindImage }, - { szCCPSearch, ACTION_CCPSearch}, + { szCCPSearch, ACTION_CCPSearch }, { szCostFinalize, ACTION_CostFinalize }, { szCostInitialize, ACTION_CostInitialize }, { szCreateFolders, ACTION_CreateFolders }, { szCreateShortcuts, ACTION_CreateShortcuts }, { szDeleteServices, ACTION_DeleteServices }, - { szDisableRollback, NULL}, + { szDisableRollback, NULL }, { szDuplicateFiles, ACTION_DuplicateFiles }, { szExecuteAction, ACTION_ExecuteAction }, { szFileCost, ACTION_FileCost }, { szFindRelatedProducts, ACTION_FindRelatedProducts }, { szForceReboot, ACTION_ForceReboot }, - { szInstallAdminPackage, NULL}, + { szInstallAdminPackage, NULL }, { szInstallExecute, ACTION_InstallExecute }, { szInstallExecuteAgain, ACTION_InstallExecute }, { szInstallFiles, ACTION_InstallFiles}, { szInstallFinalize, ACTION_InstallFinalize }, { szInstallInitialize, ACTION_InstallInitialize }, - { szInstallSFPCatalogFile, NULL}, + { szInstallSFPCatalogFile, ACTION_InstallSFPCatalogFile }, { szInstallValidate, ACTION_InstallValidate }, { szIsolateComponents, ACTION_IsolateComponents }, { szLaunchConditions, ACTION_LaunchConditions }, @@ -4764,36 +4848,36 @@ static const struct _actions StandardActions[] = { { szRegisterProduct, ACTION_RegisterProduct }, { szRegisterProgIdInfo, ACTION_RegisterProgIdInfo }, { szRegisterTypeLibraries, ACTION_RegisterTypeLibraries }, - { szRegisterUser, ACTION_RegisterUser}, - { szRemoveDuplicateFiles, NULL}, + { szRegisterUser, ACTION_RegisterUser }, + { szRemoveDuplicateFiles, ACTION_RemoveDuplicateFiles }, { szRemoveEnvironmentStrings, ACTION_RemoveEnvironmentStrings }, - { szRemoveExistingProducts, NULL}, - { szRemoveFiles, ACTION_RemoveFiles}, - { szRemoveFolders, NULL}, + { szRemoveExistingProducts, ACTION_RemoveExistingProducts }, + { szRemoveFiles, ACTION_RemoveFiles }, + { szRemoveFolders, ACTION_RemoveFolders }, { szRemoveIniValues, ACTION_RemoveIniValues }, - { szRemoveODBC, NULL}, - { szRemoveRegistryValues, NULL}, - { szRemoveShortcuts, NULL}, - { szResolveSource, ACTION_ResolveSource}, - { szRMCCPSearch, ACTION_RMCCPSearch}, - { szScheduleReboot, NULL}, + { szRemoveODBC, ACTION_RemoveODBC }, + { szRemoveRegistryValues, ACTION_RemoveRegistryValues }, + { szRemoveShortcuts, ACTION_RemoveShortcuts }, + { szResolveSource, ACTION_ResolveSource }, + { szRMCCPSearch, ACTION_RMCCPSearch }, + { szScheduleReboot, NULL }, { szSelfRegModules, ACTION_SelfRegModules }, { szSelfUnregModules, ACTION_SelfUnregModules }, - { szSetODBCFolders, NULL}, + { szSetODBCFolders, NULL }, { szStartServices, ACTION_StartServices }, { szStopServices, ACTION_StopServices }, - { szUnpublishComponents, NULL}, - { szUnpublishFeatures, NULL}, - { szUnregisterClassInfo, NULL}, - { szUnregisterComPlus, ACTION_UnregisterComPlus}, - { szUnregisterExtensionInfo, NULL}, + { szUnpublishComponents, ACTION_UnpublishComponents }, + { szUnpublishFeatures, ACTION_UnpublishFeatures }, + { szUnregisterClassInfo, ACTION_UnregisterClassInfo }, + { szUnregisterComPlus, ACTION_UnregisterComPlus }, + { szUnregisterExtensionInfo, ACTION_UnregisterExtensionInfo }, { szUnregisterFonts, ACTION_UnregisterFonts }, - { szUnregisterMIMEInfo, NULL}, - { szUnregisterProgIdInfo, NULL}, - { szUnregisterTypeLibraries, NULL}, - { szValidateProductID, ACTION_ValidateProductID}, + { szUnregisterMIMEInfo, ACTION_UnregisterMIMEInfo }, + { szUnregisterProgIdInfo, ACTION_UnregisterProgIdInfo }, + { szUnregisterTypeLibraries, ACTION_UnregisterTypeLibraries }, + { szValidateProductID, ACTION_ValidateProductID }, { szWriteEnvironmentStrings, ACTION_WriteEnvironmentStrings }, { szWriteIniValues, ACTION_WriteIniValues }, - { szWriteRegistryValues, ACTION_WriteRegistryValues}, - { NULL, NULL}, + { szWriteRegistryValues, ACTION_WriteRegistryValues }, + { NULL, NULL }, }; diff --git a/dlls/msi/automation.c b/dlls/msi/automation.c index 65639a05bdf..e8cb8875b7b 100644 --- a/dlls/msi/automation.c +++ b/dlls/msi/automation.c @@ -72,8 +72,26 @@ interface AutomationObject { VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr); + + /* A function that is called from AutomationObject::Release when the object is being freed to free any private + * data structures (or NULL) */ + void (STDMETHODCALLTYPE *funcFree)(AutomationObject* This); }; +/* + * Structures for additional data required by specific automation objects + */ + +typedef struct { + int iCount; + LPWSTR *pszStrings; +} StringListData; + +typedef struct { + /* The parent Installer object */ + IDispatch *pInstaller; +} SessionData; + /* VTables */ static const struct IDispatchVtbl AutomationObject_Vtbl; static const struct IProvideMultipleClassInfoVtbl AutomationObject_IProvideMultipleClassInfo_Vtbl; @@ -113,17 +131,19 @@ HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID * with the appropriate clsid and invocation function. */ HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOID *ppObj, REFIID clsid, HRESULT (STDMETHODCALLTYPE *funcInvoke)(AutomationObject*,DISPID,REFIID,LCID,WORD,DISPPARAMS*, - VARIANT*,EXCEPINFO*,UINT*)) + VARIANT*,EXCEPINFO*,UINT*), + void (STDMETHODCALLTYPE *funcFree)(AutomationObject*), + SIZE_T sizetPrivateData) { AutomationObject *object; HRESULT hr; - TRACE("(%ld,%p,%p,%s,%p)\n", (unsigned long)msiHandle, pUnkOuter, ppObj, debugstr_guid(clsid), funcInvoke); + TRACE("(%ld,%p,%p,%s,%p,%p,%ld)\n", (unsigned long)msiHandle, pUnkOuter, ppObj, debugstr_guid(clsid), funcInvoke, funcFree, sizetPrivateData); if( pUnkOuter ) return CLASS_E_NOAGGREGATION; - object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AutomationObject)); + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AutomationObject)+sizetPrivateData); /* Set all the VTable references */ object->lpVtbl = &AutomationObject_Vtbl; @@ -134,6 +154,7 @@ HRESULT create_automation_object(MSIHANDLE msiHandle, IUnknown *pUnkOuter, LPVOI object->msiHandle = msiHandle; object->clsid = (LPCLSID)clsid; object->funcInvoke = funcInvoke; + object->funcFree = funcFree; /* Load our TypeInfo so we don't have to process GetIDsOfNames */ object->iTypeInfo = NULL; @@ -154,6 +175,12 @@ static inline AutomationObject *obj_from_IProvideMultipleClassInfo( IProvideMult return (AutomationObject *)((char*)iface - FIELD_OFFSET(AutomationObject, lpvtblIProvideMultipleClassInfo)); } +/* Macro to get pointer to private object data */ +static inline void *private_data( AutomationObject *This ) +{ + return This + 1; +} + /* * AutomationObject methods */ @@ -209,6 +236,7 @@ static ULONG WINAPI AutomationObject_Release(IDispatch* iface) if (!ref) { + if (This->funcFree) This->funcFree(This); MsiCloseHandle(This->msiHandle); HeapFree(GetProcessHeap(), 0, This); } @@ -251,10 +279,21 @@ static HRESULT WINAPI AutomationObject_GetIDsOfNames( DISPID* rgDispId) { AutomationObject *This = (AutomationObject *)iface; + HRESULT hr; TRACE("(%p/%p)->(%p,%p,%d,%d,%p)\n", iface, This, riid, rgszNames, cNames, lcid, rgDispId); if (!IsEqualGUID(riid, &IID_NULL)) return E_INVALIDARG; - return ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId); + hr = ITypeInfo_GetIDsOfNames(This->iTypeInfo, rgszNames, cNames, rgDispId); + if (hr == DISP_E_UNKNOWNNAME) + { + int idx; + for (idx=0; idxclsid)); + } + } + return hr; } /* Maximum number of allowed function parameters+1 */ @@ -523,6 +562,7 @@ static HRESULT WINAPI RecordImpl_Invoke( if (FAILED(hr)) return hr; if ((ret = MsiRecordSetStringW(This->msiHandle, V_I4(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS) { + VariantClear(&varg1); ERR("MsiRecordSetString returned %d\n", ret); return DISP_E_EXCEPTION; } @@ -533,9 +573,68 @@ static HRESULT WINAPI RecordImpl_Invoke( return DISP_E_MEMBERNOTFOUND; } + VariantClear(&varg1); + VariantClear(&varg0); + return S_OK; } +static HRESULT WINAPI StringListImpl_Invoke( + AutomationObject* This, + DISPID dispIdMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS* pDispParams, + VARIANT* pVarResult, + EXCEPINFO* pExcepInfo, + UINT* puArgErr) +{ + StringListData *data = (StringListData *)private_data(This); + HRESULT hr; + VARIANTARG varg0; + + VariantInit(&varg0); + + switch (dispIdMember) + { + case DISPID_STRINGLIST_ITEM: + if (wFlags & DISPATCH_PROPERTYGET) { + hr = DispGetParam(pDispParams, 0, VT_I4, &varg0, puArgErr); + if (FAILED(hr)) return hr; + if (V_I4(&varg0) < 0 || V_I4(&varg0) >= data->iCount) + return DISP_E_BADINDEX; + V_VT(pVarResult) = VT_BSTR; + V_BSTR(pVarResult) = SysAllocString(data->pszStrings[V_I4(&varg0)]); + } + break; + + case DISPID_STRINGLIST_COUNT: + if (wFlags & DISPATCH_PROPERTYGET) { + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = data->iCount; + } + break; + + default: + return DISP_E_MEMBERNOTFOUND; + } + + VariantClear(&varg0); + + return S_OK; +} + +static void WINAPI StringListImpl_Free(AutomationObject *This) +{ + StringListData *data = private_data(This); + int idx; + + for (idx=0; idxiCount; idx++) + SysFreeString(data->pszStrings[idx]); + HeapFree(GetProcessHeap(), 0, data->pszStrings); +} + static HRESULT WINAPI ViewImpl_Invoke( AutomationObject* This, DISPID dispIdMember, @@ -575,11 +674,13 @@ static HRESULT WINAPI ViewImpl_Invoke( V_VT(pVarResult) = VT_DISPATCH; if ((ret = MsiViewFetch(This->msiHandle, &msiHandle)) == ERROR_SUCCESS) { - if (SUCCEEDED(create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_Record, RecordImpl_Invoke))) + if (SUCCEEDED(hr = create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_Record, RecordImpl_Invoke, NULL, 0))) { IDispatch_AddRef(pDispatch); V_DISPATCH(pVarResult) = pDispatch; } + else + ERR("Failed to create Record object, hresult 0x%08x\n", hr); } else if (ret == ERROR_NO_MORE_ITEMS) V_DISPATCH(pVarResult) = NULL; @@ -602,6 +703,9 @@ static HRESULT WINAPI ViewImpl_Invoke( return DISP_E_MEMBERNOTFOUND; } + VariantClear(&varg1); + VariantClear(&varg0); + return S_OK; } @@ -635,14 +739,17 @@ static HRESULT WINAPI DatabaseImpl_Invoke( V_VT(pVarResult) = VT_DISPATCH; if ((ret = MsiDatabaseOpenViewW(This->msiHandle, V_BSTR(&varg0), &msiHandle)) == ERROR_SUCCESS) { - if (SUCCEEDED(create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_View, ViewImpl_Invoke))) + if (SUCCEEDED(hr = create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_View, ViewImpl_Invoke, NULL, 0))) { IDispatch_AddRef(pDispatch); V_DISPATCH(pVarResult) = pDispatch; } + else + ERR("Failed to create View object, hresult 0x%08x\n", hr); } else { + VariantClear(&varg0); ERR("MsiDatabaseOpenView returned %d\n", ret); return DISP_E_EXCEPTION; } @@ -653,6 +760,9 @@ static HRESULT WINAPI DatabaseImpl_Invoke( return DISP_E_MEMBERNOTFOUND; } + VariantClear(&varg1); + VariantClear(&varg0); + return S_OK; } @@ -667,6 +777,7 @@ static HRESULT WINAPI SessionImpl_Invoke( EXCEPINFO* pExcepInfo, UINT* puArgErr) { + SessionData *data = private_data(This); WCHAR *szString; DWORD dwLen; IDispatch *pDispatch = NULL; @@ -682,6 +793,14 @@ static HRESULT WINAPI SessionImpl_Invoke( switch (dispIdMember) { + case DISPID_SESSION_INSTALLER: + if (wFlags & DISPATCH_PROPERTYGET) { + V_VT(pVarResult) = VT_DISPATCH; + IDispatch_AddRef(data->pInstaller); + V_DISPATCH(pVarResult) = data->pInstaller; + } + break; + case DISPID_SESSION_PROPERTY: if (wFlags & DISPATCH_PROPERTYGET) { hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); @@ -711,6 +830,8 @@ static HRESULT WINAPI SessionImpl_Invoke( } if ((ret = MsiSetPropertyW(This->msiHandle, V_BSTR(&varg0), V_BSTR(&varg1))) != ERROR_SUCCESS) { + VariantClear(&varg0); + VariantClear(&varg1); ERR("MsiSetProperty returned %d\n", ret); return DISP_E_EXCEPTION; } @@ -749,11 +870,13 @@ static HRESULT WINAPI SessionImpl_Invoke( V_VT(pVarResult) = VT_DISPATCH; if ((msiHandle = MsiGetActiveDatabase(This->msiHandle))) { - if (SUCCEEDED(create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_Database, DatabaseImpl_Invoke))) + if (SUCCEEDED(hr = create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_Database, DatabaseImpl_Invoke, NULL, 0))) { IDispatch_AddRef(pDispatch); V_DISPATCH(pVarResult) = pDispatch; } + else + ERR("Failed to create Database object, hresult 0x%08x\n", hr); } else { @@ -796,6 +919,7 @@ static HRESULT WINAPI SessionImpl_Invoke( V_I4(pVarResult) = msiDoActionStatusBadActionData; break; default: + VariantClear(&varg0); FIXME("MsiDoAction returned unhandled value %d\n", ret); return DISP_E_EXCEPTION; } @@ -849,6 +973,7 @@ static HRESULT WINAPI SessionImpl_Invoke( } if ((ret = MsiSetFeatureStateW(This->msiHandle, V_BSTR(&varg0), V_I4(&varg1))) != ERROR_SUCCESS) { + VariantClear(&varg0); ERR("MsiSetFeatureState returned %d\n", ret); return DISP_E_EXCEPTION; } @@ -859,6 +984,9 @@ static HRESULT WINAPI SessionImpl_Invoke( return DISP_E_MEMBERNOTFOUND; } + VariantClear(&varg1); + VariantClear(&varg0); + return S_OK; } @@ -890,39 +1018,101 @@ static HRESULT WINAPI InstallerImpl_Invoke( hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); if (FAILED(hr)) return hr; hr = DispGetParam(pDispParams, 1, VT_I4, &varg1, puArgErr); - if (FAILED(hr)) return hr; + if (FAILED(hr)) + { + VariantClear(&varg0); + return hr; + } V_VT(pVarResult) = VT_DISPATCH; if ((ret = MsiOpenPackageExW(V_BSTR(&varg0), V_I4(&varg1), &msiHandle)) == ERROR_SUCCESS) { - if (SUCCEEDED(create_automation_object(msiHandle, NULL, (LPVOID*)&pDispatch, &DIID_Session, SessionImpl_Invoke))) + if (SUCCEEDED(hr = create_session(msiHandle, (IDispatch *)This, &pDispatch))) { IDispatch_AddRef(pDispatch); V_DISPATCH(pVarResult) = pDispatch; } + else + ERR("Failed to create Session object, hresult 0x%08x\n", hr); } else { + VariantClear(&varg0); ERR("MsiOpenPackageEx returned %d\n", ret); return DISP_E_EXCEPTION; } } break; + case DISPID_INSTALLER_PRODUCTSTATE: + if (wFlags & DISPATCH_PROPERTYGET) { + hr = DispGetParam(pDispParams, 0, VT_BSTR, &varg0, puArgErr); + if (FAILED(hr)) return hr; + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = MsiQueryProductStateW(V_BSTR(&varg0)); + } + break; + + case DISPID_INSTALLER_PRODUCTS: + if (wFlags & DISPATCH_PROPERTYGET) + { + StringListData *sldata = NULL; + int idx = 0; + WCHAR szProductBuf[GUID_SIZE]; + + /* Find number of products */ + do { + ret = MsiEnumProductsW(idx, szProductBuf); + if (ret == ERROR_SUCCESS) idx++; + } while (ret == ERROR_SUCCESS && ret != ERROR_NO_MORE_ITEMS); + + if (ret != ERROR_SUCCESS && ret != ERROR_NO_MORE_ITEMS) + { + ERR("MsiEnumProducts returned %d\n", ret); + return DISP_E_EXCEPTION; + } + + V_VT(pVarResult) = VT_DISPATCH; + if (SUCCEEDED(hr = create_automation_object(0, NULL, (LPVOID*)&pDispatch, &DIID_StringList, StringListImpl_Invoke, StringListImpl_Free, sizeof(StringListData)))) + { + IDispatch_AddRef(pDispatch); + V_DISPATCH(pVarResult) = pDispatch; + + /* Save product strings */ + sldata = (StringListData *)private_data((AutomationObject *)pDispatch); + sldata->iCount = idx; + sldata->pszStrings = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LPWSTR)*sldata->iCount); + for (idx = 0; idx < sldata->iCount; idx++) + { + ret = MsiEnumProductsW(idx, szProductBuf); + sldata->pszStrings[idx] = SysAllocString(szProductBuf); + } + } + else + ERR("Failed to create StringList object, hresult 0x%08x\n", hr); + } + break; + default: return DISP_E_MEMBERNOTFOUND; } + VariantClear(&varg1); + VariantClear(&varg0); + return S_OK; } /* Wrapper around create_automation_object to create an installer object. */ HRESULT create_msiserver(IUnknown *pOuter, LPVOID *ppObj) { - return create_automation_object(0, pOuter, ppObj, &DIID_Installer, InstallerImpl_Invoke); + return create_automation_object(0, pOuter, ppObj, &DIID_Installer, InstallerImpl_Invoke, NULL, 0); } /* Wrapper around create_automation_object to create a session object. */ -HRESULT create_session(MSIHANDLE msiHandle, IDispatch **pDispatch) +HRESULT create_session(MSIHANDLE msiHandle, IDispatch *pInstaller, IDispatch **pDispatch) { - return create_automation_object(msiHandle, NULL, (LPVOID)pDispatch, &DIID_Session, SessionImpl_Invoke); + HRESULT hr = create_automation_object(msiHandle, NULL, (LPVOID)pDispatch, &DIID_Session, SessionImpl_Invoke, NULL, sizeof(SessionData)); + if (SUCCEEDED(hr) && pDispatch && *pDispatch) + ((SessionData *)private_data((AutomationObject *)*pDispatch))->pInstaller = pInstaller; + return hr; } diff --git a/dlls/msi/dialog.c b/dlls/msi/dialog.c index 35a192cffe1..614b4aa4d58 100644 --- a/dlls/msi/dialog.c +++ b/dlls/msi/dialog.c @@ -265,11 +265,11 @@ static LPWSTR msi_dialog_get_style( LPCWSTR p, LPCWSTR *rest ) while ((first = strchrW( p, '{' )) && (q = strchrW( first + 1, '}' ))) { p = first + 1; - if( *p == '\\' || *p == '&' ) - p++; + if( *p != '\\' && *p != '&' ) + return NULL; /* little bit of sanity checking to stop us getting confused with RTF */ - for( i=p; ihandler = msi_dialog_edit_handler; + + text = MSI_RecordGetString( rec, 10 ); + if ( text ) + { + begin = strchrW( text, '{' ); + end = strchrW( text, '}' ); + + if ( begin && end && end > begin ) + { + lstrcpynW( num, begin + 1, end - begin ); + limit = atolW( num ); + + SendMessageW( control->hwnd, EM_SETLIMITTEXT, limit, 0 ); + } + } + prop = MSI_RecordGetString( rec, 9 ); if( prop ) control->property = strdupW( prop ); + val = msi_dup_property( dialog->package, control->property ); SetWindowTextW( control->hwnd, val ); msi_free( val ); @@ -3166,8 +3185,7 @@ static LRESULT msi_dialog_oncommand( msi_dialog *dialog, WPARAM param, HWND hwnd msi_dialog_evaluate_control_conditions( dialog ); } } - else - ERR("button click from nowhere %p %d %p\n", dialog, param, hwnd); + return 0; } diff --git a/dlls/msi/events.c b/dlls/msi/events.c index 714e060ae1d..faaaf2f0d0c 100644 --- a/dlls/msi/events.c +++ b/dlls/msi/events.c @@ -406,6 +406,13 @@ static UINT ControlEvent_DirectoryListUp(MSIPACKAGE *package, LPCWSTR argument, return msi_dialog_directorylist_up( dialog ); } +static UINT ControlEvent_ReinstallMode(MSIPACKAGE *package, LPCWSTR argument, + msi_dialog *dialog) +{ + static const WCHAR szReinstallMode[] = {'R','E','I','N','S','T','A','L','L','M','O','D','E',0}; + return MSI_SetPropertyW( package, szReinstallMode, argument ); +} + static const struct _events Events[] = { { "EndDialog",ControlEvent_EndDialog }, { "NewDialog",ControlEvent_NewDialog }, @@ -420,6 +427,7 @@ static const struct _events Events[] = { { "SetInstallLevel",ControlEvent_SetInstallLevel }, { "DirectoryListUp",ControlEvent_DirectoryListUp }, { "SelectionBrowse",ControlEvent_SpawnDialog }, + { "ReinstallMode",ControlEvent_ReinstallMode }, { NULL,NULL }, }; diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index de08aeb0dc8..a8d833fa676 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -793,7 +793,7 @@ extern VOID ControlEvent_UnSubscribeToEvent( MSIPACKAGE *package, LPCWSTR event, /* OLE automation */ extern HRESULT create_msiserver(IUnknown *pOuter, LPVOID *ppObj); -extern HRESULT create_session(MSIHANDLE msiHandle, IDispatch **pDispatch); +extern HRESULT create_session(MSIHANDLE msiHandle, IDispatch *pInstaller, IDispatch **pDispatch); extern HRESULT load_type_info(IDispatch *iface, ITypeInfo **pptinfo, REFIID clsid, LCID lcid); /* Scripting */ diff --git a/dlls/msi/msiserver.idl b/dlls/msi/msiserver.idl index 4d6c00b6759..e9f6169d2a6 100644 --- a/dlls/msi/msiserver.idl +++ b/dlls/msi/msiserver.idl @@ -38,6 +38,22 @@ library WindowsInstaller dispinterface Product; dispinterface Patch; + typedef enum { + msiInstallStateNotUsed = -7, + msiInstallStateBadConfig = -6, + msiInstallStateIncomplete = -5, + msiInstallStateSourceAbsent = -4, + msiInstallStateInvalidArg = -2, + msiInstallStateUnknown = -1, + msiInstallStateBroken = 0, + msiInstallStateAdvertised = 1, + msiInstallStateRemoved = 1, + msiInstallStateAbsent = 2, + msiInstallStateLocal = 3, + msiInstallStateSource = 4, + msiInstallStateDefault = 5 + } MsiInstallState; + [ uuid(000C1090-0000-0000-C000-000000000046) ] dispinterface Installer { @@ -45,8 +61,13 @@ library WindowsInstaller methods: [id(DISPID_INSTALLER_OPENPACKAGE)] Session* OpenPackage( - [in] VARIANT Path, - [in, optional, defaultvalue(0)] long OptionalOption); + [in] VARIANT PackagePath, + [in, optional, defaultvalue(0)] long Options); + [id(DISPID_INSTALLER_PRODUCTSTATE), propget] + MsiInstallState ProductState( + [in] BSTR Product); + [id(DISPID_INSTALLER_PRODUCTS), propget] + StringList *Products(); } [ uuid(000C1093-0000-0000-C000-000000000046) ] @@ -55,10 +76,10 @@ library WindowsInstaller properties: methods: [id(DISPID_RECORD_STRINGDATA), propget] - BSTR StringData([in] long FieldNumber); + BSTR StringData([in] long Field); [id(DISPID_RECORD_STRINGDATA), propput] void StringData( - [in] long FieldNumber, + [in] long Field, [in] BSTR rhs); } @@ -67,6 +88,10 @@ library WindowsInstaller { properties: methods: + [id(DISPID_STRINGLIST_ITEM), propget] + BSTR Item(long Index); + [id(DISPID_STRINGLIST_COUNT), propget] + long Count(); } [ uuid(000C1096-0000-0000-C000-000000000046) ] @@ -96,7 +121,7 @@ library WindowsInstaller properties: methods: [id(DISPID_VIEW_EXECUTE)] - void Execute([in, optional, defaultvalue(0)] Record *OptionalRecord); + void Execute([in, optional, defaultvalue(0)] Record *Params); [id(DISPID_VIEW_FETCH)] Record* Fetch(); [id(DISPID_VIEW_CLOSE)] @@ -109,7 +134,7 @@ library WindowsInstaller properties: methods: [id(DISPID_DATABASE_OPENVIEW)] - View* OpenView([in] BSTR QueryString); + View* OpenView([in] BSTR Sql); } typedef enum { @@ -142,55 +167,41 @@ library WindowsInstaller msiRunModeCommit = 18 } MsiRunMode; - typedef enum { - msiInstallStateNotUsed = -7, - msiInstallStateBadConfig = -6, - msiInstallStateIncomplete = -5, - msiInstallStateSourceAbsent = -4, - msiInstallStateInvalidArg = -2, - msiInstallStateUnknown = -1, - msiInstallStateBroken = 0, - msiInstallStateAdvertised = 1, - msiInstallStateRemoved = 1, - msiInstallStateAbsent = 2, - msiInstallStateLocal = 3, - msiInstallStateSource = 4, - msiInstallStateDefault = 5 - } MsiInstallState; - [ uuid(000C109E-0000-0000-C000-000000000046) ] dispinterface Session { properties: methods: + [id(DISPID_SESSION_INSTALLER), propget] + Installer *Installer(); [id(DISPID_SESSION_PROPERTY), propget] - BSTR Property([in] BSTR PropertyName); + BSTR Property([in] BSTR Name); [id(DISPID_SESSION_PROPERTY), propput] void Property( - [in] BSTR PropertyName, + [in] BSTR Name, [in] BSTR rhs); [id(DISPID_SESSION_LANGUAGE), propget] long Language(); [id(DISPID_SESSION_MODE), propget] - VARIANT_BOOL Mode([in] MsiRunMode runMode); + VARIANT_BOOL Mode([in] MsiRunMode Flag); [id(DISPID_SESSION_MODE), propput] void Mode( - [in] MsiRunMode runMode, + [in] MsiRunMode Flag, [in] VARIANT_BOOL rhs); [id(DISPID_SESSION_DATABASE), propget] Database* Database(); [id(DISPID_SESSION_DOACTION)] - MsiDoActionStatus DoAction([in] BSTR ActionString); + MsiDoActionStatus DoAction([in] BSTR Action); [id(DISPID_SESSION_FEATURECURRENTSTATE), propget] - MsiInstallState FeatureCurrentState([in] BSTR FeatureName); + MsiInstallState FeatureCurrentState([in] BSTR Feature); [id(DISPID_SESSION_FEATUREREQUESTSTATE), propget] - MsiInstallState FeatureRequestState([in] BSTR FeatureName); + MsiInstallState FeatureRequestState([in] BSTR Feature); [id(DISPID_SESSION_FEATUREREQUESTSTATE), propput] void FeatureRequestState( - [in] BSTR FeatureName, + [in] BSTR Feature, [in] MsiInstallState rhs); [id(DISPID_SESSION_SETINSTALLLEVEL)] - void SetInstallLevel([in] long InstallLevel); + void SetInstallLevel([in] long Level); } [ uuid(000C109F-0000-0000-C000-000000000046) ] diff --git a/dlls/msi/msiserver_dispids.h b/dlls/msi/msiserver_dispids.h index 1c7a17f5af3..daca2789d32 100644 --- a/dlls/msi/msiserver_dispids.h +++ b/dlls/msi/msiserver_dispids.h @@ -17,15 +17,21 @@ */ #define DISPID_INSTALLER_OPENPACKAGE 2 +#define DISPID_INSTALLER_PRODUCTSTATE 17 +#define DISPID_INSTALLER_PRODUCTS 35 #define DISPID_RECORD_STRINGDATA 1 +#define DISPID_STRINGLIST_ITEM 0 +#define DISPID_STRINGLIST_COUNT 1 + #define DISPID_VIEW_EXECUTE 1 #define DISPID_VIEW_FETCH 2 #define DISPID_VIEW_CLOSE 4 #define DISPID_DATABASE_OPENVIEW 3 +#define DISPID_SESSION_INSTALLER 1 #define DISPID_SESSION_PROPERTY 2 #define DISPID_SESSION_LANGUAGE 3 #define DISPID_SESSION_MODE 4 diff --git a/dlls/msi/package.c b/dlls/msi/package.c index e04e19c90da..655cf8f9236 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -22,7 +22,6 @@ #define NONAMELESSSTRUCT #include -#include #include "windef.h" #include "winbase.h" #include "winreg.h" @@ -1105,12 +1104,10 @@ UINT MSI_SetPropertyW( MSIPACKAGE *package, LPCWSTR szName, LPCWSTR szValue) if (rc == ERROR_SUCCESS) { rc = MSI_ViewExecute(view, row); - if (rc != ERROR_SUCCESS) printf("MSI_ViewExecute failed: %d\n", rc); - MSI_ViewClose(view); msiobj_release(&view->hdr); } - else printf("MSI_DatabaseOpenView failed: %d\n", rc); + msiobj_release(&row->hdr); return rc; diff --git a/dlls/msi/script.c b/dlls/msi/script.c index f2fc6426dfc..54d0ee817e4 100644 --- a/dlls/msi/script.c +++ b/dlls/msi/script.c @@ -46,6 +46,7 @@ static const WCHAR szSession[] = {'S','e','s','s','i','o','n',0}; typedef struct { IActiveScriptSite lpVtbl; + IDispatch *pInstaller; IDispatch *pSession; LONG ref; } MsiActiveScriptSite; @@ -65,6 +66,7 @@ static HRESULT create_ActiveScriptSite(IUnknown *pUnkOuter, LPVOID *ppObj) object->lpVtbl.lpVtbl = &ASS_Vtbl; object->ref = 1; + object->pInstaller = NULL; object->pSession = NULL; *ppObj = object; @@ -97,15 +99,20 @@ DWORD call_script(MSIHANDLE hPackage, INT type, LPCWSTR script, LPCWSTR function hr = create_ActiveScriptSite(NULL, (void **)&pActiveScriptSite); if (hr != S_OK) goto done; + /* Create an installer object */ + hr = create_msiserver(NULL, (LPVOID *)&pActiveScriptSite->pInstaller); + if (hr != S_OK) goto done; + IUnknown_AddRef((IUnknown *)pActiveScriptSite->pInstaller); + /* Create a session object */ - hr = create_session(hPackage, &pActiveScriptSite->pSession); + hr = create_session(hPackage, pActiveScriptSite->pInstaller, &pActiveScriptSite->pSession); if (hr != S_OK) goto done; IUnknown_AddRef((IUnknown *)pActiveScriptSite->pSession); /* Create the scripting engine */ - if (type & msidbCustomActionTypeJScript) + if ((type & 7) == msidbCustomActionTypeJScript) hr = CLSIDFromProgID(szJScript, &clsid); - else if (type & msidbCustomActionTypeVBScript) + else if ((type & 7) == msidbCustomActionTypeVBScript) hr = CLSIDFromProgID(szVBScript, &clsid); else { ERR("Unknown script type %d\n", type); @@ -181,6 +188,8 @@ done: if (pActiveScript) IActiveScriptSite_Release(pActiveScript); if (pActiveScriptSite && pActiveScriptSite->pSession) IUnknown_Release((IUnknown *)pActiveScriptSite->pSession); + if (pActiveScriptSite && + pActiveScriptSite->pInstaller) IUnknown_Release((IUnknown *)pActiveScriptSite->pInstaller); if (pActiveScriptSite) IUnknown_Release((IUnknown *)pActiveScriptSite); CoUninitialize(); /* must call even if CoInitialize failed */ diff --git a/dlls/msi/tests/automation.c b/dlls/msi/tests/automation.c index c84c54b3447..26781635197 100644 --- a/dlls/msi/tests/automation.c +++ b/dlls/msi/tests/automation.c @@ -261,18 +261,13 @@ static void create_database(const CHAR *name, const msi_table *tables, int num_t /* ok-like statement which takes two unicode strings as arguments */ static CHAR string1[MAX_PATH], string2[MAX_PATH]; -static UINT len; #define ok_w2(format, szString1, szString2) \ \ if (lstrcmpW(szString1, szString2) != 0) \ { \ - len = WideCharToMultiByte(CP_ACP, 0, szString1, -1, string1, MAX_PATH, NULL, NULL); \ - ok(len, "WideCharToMultiByteChar returned error %d\n", GetLastError()); \ -\ - len = WideCharToMultiByte(CP_ACP, 0, szString2, -1, string2, MAX_PATH, NULL, NULL); \ - ok(len, "WideCharToMultiByteChar returned error %d\n", GetLastError()); \ -\ + WideCharToMultiByte(CP_ACP, 0, szString1, -1, string1, MAX_PATH, NULL, NULL); \ + WideCharToMultiByte(CP_ACP, 0, szString2, -1, string2, MAX_PATH, NULL, NULL); \ ok(0, format, string1, string2); \ } @@ -290,19 +285,8 @@ static WCHAR szSource[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0 ok_w2("Exception source was \"%s\" but expected to be \"%s\"\n", excepinfo.bstrSource, szSource); \ \ ok(excepinfo.bstrDescription != NULL, "Exception description was NULL\n"); \ - if (excepinfo.bstrDescription && lstrcmpW(excepinfo.bstrDescription, szDescription) != 0) \ - { \ - len = WideCharToMultiByte(CP_ACP, 0, excepinfo.bstrDescription, -1, string1, MAX_PATH, NULL, NULL); \ - ok(len, "WideCharToMultiByteChar returned error %d\n", GetLastError()); \ - \ - len = WideCharToMultiByte(CP_ACP, 0, szDescription, -1, string2, MAX_PATH, NULL, NULL); \ - ok(len, "WideCharToMultiByteChar returned error %d\n", GetLastError()); \ - \ - todo_wine { \ - /* Our parameter names are different so the descriptions will not match */ \ - ok(0, "Exception description was \"%s\" but expected to be \"%s\"\n", string1, string2); \ - } \ - } \ + if (excepinfo.bstrDescription) \ + ok_w2("Exception description was \"%s\" but expected to be \"%s\"\n", excepinfo.bstrDescription, szDescription); \ } static DISPID get_dispid( IDispatch *disp, const char *name ) @@ -328,10 +312,11 @@ static DISPID get_dispid( IDispatch *disp, const char *name ) static void test_dispid(void) { - ok( get_dispid( pInstaller, "OpenPackage" ) == 2, "dispid wrong\n"); - todo_wine { ok( get_dispid( pInstaller, "CreateRecord" ) == 1, "dispid wrong\n"); + } + ok( get_dispid( pInstaller, "OpenPackage" ) == 2, "dispid wrong\n"); + todo_wine { ok( get_dispid( pInstaller, "OpenProduct" ) == 3, "dispid wrong\n"); ok( get_dispid( pInstaller, "OpenDatabase" ) == 4, "dispid wrong\n"); ok( get_dispid( pInstaller, "SummaryInformation" ) == 5, "dispid wrong\n"); @@ -346,7 +331,9 @@ static void test_dispid(void) ok( get_dispid( pInstaller, "FileSize" ) == 15, "dispid wrong\n"); ok( get_dispid( pInstaller, "FileVersion" ) == 16, "dispid wrong\n"); + } ok( get_dispid( pInstaller, "ProductState" ) == 17, "dispid wrong\n"); + todo_wine { ok( get_dispid( pInstaller, "ProductInfo" ) == 18, "dispid wrong\n"); ok( get_dispid( pInstaller, "ConfigureProduct" ) == 19, "dispid wrong\n"); ok( get_dispid( pInstaller, "ReinstallProduct" ) == 20 , "dispid wrong\n"); @@ -364,7 +351,9 @@ static void test_dispid(void) ok( get_dispid( pInstaller, "ProvideQualifiedComponent" ) == 32, "dispid wrong\n"); ok( get_dispid( pInstaller, "QualifierDescription" ) == 33, "dispid wrong\n"); ok( get_dispid( pInstaller, "ComponentQualifiers" ) == 34, "dispid wrong\n"); + } ok( get_dispid( pInstaller, "Products" ) == 35, "dispid wrong\n"); + todo_wine { ok( get_dispid( pInstaller, "Features" ) == 36, "dispid wrong\n"); ok( get_dispid( pInstaller, "Components" ) == 37, "dispid wrong\n"); ok( get_dispid( pInstaller, "ComponentClients" ) == 38, "dispid wrong\n"); @@ -515,6 +504,74 @@ static HRESULT Installer_CreateRecord(int count, IDispatch **pRecord) return hr; } +static HRESULT Installer_RegistryValue(HKEY hkey, LPCWSTR szKey, BOOL *pBool) +{ + VARIANT varresult; + VARIANTARG vararg[3]; + DISPPARAMS dispparams = {vararg, NULL, sizeof(vararg)/sizeof(VARIANTARG), 0}; + HRESULT hr; + + VariantInit(&vararg[2]); + V_VT(&vararg[2]) = VT_I4; + V_I4(&vararg[2]) = (int)hkey; + VariantInit(&vararg[1]); + V_VT(&vararg[1]) = VT_BSTR; + V_BSTR(&vararg[1]) = SysAllocString(szKey); + VariantInit(&vararg[0]); + V_VT(&vararg[0]) = VT_EMPTY; + + hr = invoke(pInstaller, "RegistryValue", DISPATCH_METHOD, &dispparams, &varresult, VT_BOOL); + *pBool = V_BOOL(&varresult); + VariantClear(&varresult); + return hr; +} + +static HRESULT Installer_RegistryValueW(HKEY hkey, LPCWSTR szKey, LPCWSTR szValue, LPWSTR szString) +{ + VARIANT varresult; + VARIANTARG vararg[3]; + DISPPARAMS dispparams = {vararg, NULL, sizeof(vararg)/sizeof(VARIANTARG), 0}; + HRESULT hr; + + VariantInit(&vararg[2]); + V_VT(&vararg[2]) = VT_I4; + V_I4(&vararg[2]) = (int)hkey; + VariantInit(&vararg[1]); + V_VT(&vararg[1]) = VT_BSTR; + V_BSTR(&vararg[1]) = SysAllocString(szKey); + VariantInit(&vararg[0]); + V_VT(&vararg[0]) = VT_BSTR; + V_BSTR(&vararg[0]) = SysAllocString(szValue); + + hr = invoke(pInstaller, "RegistryValue", DISPATCH_METHOD, &dispparams, &varresult, VT_BSTR); + lstrcpyW(szString, V_BSTR(&varresult)); + VariantClear(&varresult); + return hr; +} + +static HRESULT Installer_RegistryValueI(HKEY hkey, LPCWSTR szKey, int iValue, LPWSTR szString, VARTYPE vtResult) +{ + VARIANT varresult; + VARIANTARG vararg[3]; + DISPPARAMS dispparams = {vararg, NULL, sizeof(vararg)/sizeof(VARIANTARG), 0}; + HRESULT hr; + + VariantInit(&vararg[2]); + V_VT(&vararg[2]) = VT_I4; + V_I4(&vararg[2]) = (int)hkey; + VariantInit(&vararg[1]); + V_VT(&vararg[1]) = VT_BSTR; + V_BSTR(&vararg[1]) = SysAllocString(szKey); + VariantInit(&vararg[0]); + V_VT(&vararg[0]) = VT_I4; + V_I4(&vararg[0]) = iValue; + + hr = invoke(pInstaller, "RegistryValue", DISPATCH_METHOD, &dispparams, &varresult, vtResult); + if (vtResult == VT_BSTR) lstrcpyW(szString, V_BSTR(&varresult)); + VariantClear(&varresult); + return hr; +} + static HRESULT Installer_OpenPackage(LPCWSTR szPackagePath, int options, IDispatch **pSession) { VARIANT varresult; @@ -534,6 +591,34 @@ static HRESULT Installer_OpenPackage(LPCWSTR szPackagePath, int options, IDispat return hr; } +static HRESULT Installer_ProductState(LPCWSTR szProduct, int *pInstallState) +{ + VARIANT varresult; + VARIANTARG vararg[1]; + DISPPARAMS dispparams = {vararg, NULL, sizeof(vararg)/sizeof(VARIANTARG), 0}; + HRESULT hr; + + VariantInit(&vararg[0]); + V_VT(&vararg[0]) = VT_BSTR; + V_BSTR(&vararg[0]) = SysAllocString(szProduct); + + hr = invoke(pInstaller, "ProductState", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4); + *pInstallState = V_I4(&varresult); + VariantClear(&varresult); + return hr; +} + +static HRESULT Installer_Products(IDispatch **pStringList) +{ + VARIANT varresult; + DISPPARAMS dispparams = {NULL, NULL, 0, 0}; + HRESULT hr; + + hr = invoke(pInstaller, "Products", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH); + *pStringList = V_DISPATCH(&varresult); + return hr; +} + static HRESULT Installer_VersionGet(LPCWSTR szVersion) { VARIANT varresult; @@ -546,6 +631,17 @@ static HRESULT Installer_VersionGet(LPCWSTR szVersion) return hr; } +static HRESULT Session_Installer(IDispatch *pSession, IDispatch **pInst) +{ + VARIANT varresult; + DISPPARAMS dispparams = {NULL, NULL, 0, 0}; + HRESULT hr; + + hr = invoke(pSession, "Installer", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH); + *pInst = V_DISPATCH(&varresult); + return hr; +} + static HRESULT Session_PropertyGet(IDispatch *pSession, LPCWSTR szName, LPCWSTR szReturn) { VARIANT varresult; @@ -807,6 +903,33 @@ static HRESULT Record_StringDataPut(IDispatch *pRecord, int iField, LPCWSTR szSt return invoke(pRecord, "StringData", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_BSTR); } +static HRESULT StringList_Item(IDispatch *pStringList, int iIndex, LPWSTR szString) +{ + VARIANT varresult; + VARIANTARG vararg[1]; + DISPPARAMS dispparams = {vararg, NULL, sizeof(vararg)/sizeof(VARIANTARG), 0}; + HRESULT hr; + + VariantInit(&vararg[0]); + V_VT(&vararg[0]) = VT_I4; + V_I4(&vararg[0]) = iIndex; + + hr = invoke(pStringList, "Item", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR); + lstrcpyW(szString, V_BSTR(&varresult)); + VariantClear(&varresult); + return hr; +} + +static HRESULT StringList_Count(IDispatch *pStringList, int *pCount) +{ + VARIANT varresult; + DISPPARAMS dispparams = {NULL, NULL, 0, 0}; + HRESULT hr = invoke(pStringList, "Count", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4); + *pCount = V_I4(&varresult); + VariantClear(&varresult); + return hr; +} + /* Test the various objects */ static void test_Database(IDispatch *pDatabase) @@ -893,9 +1016,15 @@ static void test_Session(IDispatch *pSession) UINT len; BOOL bool; int myint; - IDispatch *pDatabase = NULL; + IDispatch *pDatabase = NULL, *pInst = NULL; HRESULT hr; + /* Session::Installer */ + hr = Session_Installer(pSession, &pInst); + ok(SUCCEEDED(hr), "Session_Installer failed, hresult 0x%08x\n", hr); + ok(pInst != NULL, "Session_Installer returned NULL IDispatch pointer\n"); + ok(pInst == pInstaller, "Session_Installer does not match Installer instance from CoCreateInstance\n"); + /* Session::Property, get */ memset(stringw, 0, sizeof(stringw)); hr = Session_PropertyGet(pSession, szProductName, stringw); @@ -979,13 +1108,131 @@ static void test_Session(IDispatch *pSession) ok(myint == INSTALLSTATE_ADVERTISED, "Feature request state was %d but expected %d\n", myint, INSTALLSTATE_ADVERTISED); } +/* delete key and all its subkeys */ +static DWORD delete_key( HKEY hkey ) +{ + char name[MAX_PATH]; + DWORD ret; + + while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name)))) + { + HKEY tmp; + if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp ))) + { + ret = delete_key( tmp ); + RegCloseKey( tmp ); + } + if (ret) break; + } + if (ret != ERROR_NO_MORE_ITEMS) return ret; + RegDeleteKeyA( hkey, "" ); + return 0; +} + +static void test_Installer_RegistryValue(void) +{ + static const DWORD qw[2] = { 0x12345678, 0x87654321 }; + static const WCHAR szKey[] = { 'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','T','e','s','t',0 }; + static const WCHAR szOne[] = { 'O','n','e',0 }; + static const WCHAR szTwo[] = { 'T','w','o',0 }; + static const WCHAR szThree[] = { 'T','h','r','e','e',0 }; + static const WCHAR szFour[] = { 'F','o','u','r',0 }; + static const WCHAR szBlank[] = { 0 }; + WCHAR szString[MAX_PATH]; + HKEY hkey, hkey_sub; + HRESULT hr; + BOOL bRet; + + /* Delete keys */ + if (!RegOpenKeyW( HKEY_CURRENT_USER, szKey, &hkey )) delete_key( hkey ); + + /* Does our key exist? Shouldn't; two different ways to check */ + todo_wine { + hr = Installer_RegistryValue(HKEY_CURRENT_USER, szKey, &bRet); + ok(SUCCEEDED(hr), "Installer_RegistryValue failed, hresult 0x%08x\n", hr); + if (SUCCEEDED(hr)) + ok(!bRet, "Registry key expected to not exist, but Installer_RegistryValue claims it does\n"); + + memset(szString, 0, sizeof(szString)); + hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, NULL, szString); + ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueW failed, hresult 0x%08x\n", hr); + } + + /* Create key */ + ok(!RegCreateKeyW( HKEY_CURRENT_USER, szKey, &hkey ), "RegCreateKeyW failed\n"); + + ok(!RegSetValueExW(hkey,szOne,0,REG_SZ, (const BYTE *)szOne, sizeof(szOne)), + "RegSetValueExW failed\n"); + ok(!RegSetValueExW(hkey,szTwo,0,REG_DWORD, (const BYTE *)qw, 4), + "RegSetValueExW failed\n"); + ok(!RegSetValueExW(hkey,szThree,0,REG_BINARY, (const BYTE *)qw, 4), + "RegSetValueExW failed\n"); + ok(!RegSetValueExW(hkey,NULL,0,REG_SZ, (const BYTE *)szOne, sizeof(szOne)), + "RegSetValueExW failed\n"); + + ok(!RegCreateKeyW( hkey, szFour, &hkey_sub ), "RegCreateKeyW failed\n"); + + todo_wine { + /* Does our key exist? It should, and make sure we retrieve the correct default value */ + bRet = FALSE; + hr = Installer_RegistryValue(HKEY_CURRENT_USER, szKey, &bRet); + ok(SUCCEEDED(hr), "Installer_RegistryValue failed, hresult 0x%08x\n", hr); + if (SUCCEEDED(hr)) + ok(bRet, "Registry key expected to exist, but Installer_RegistryValue claims it does not\n"); + + memset(szString, 0, sizeof(szString)); + hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, NULL, szString); + ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr); + ok_w2("Default registry value \"%s\" does not match expected \"%s\"\n", szString, szOne); + + /* Get value of key */ + memset(szString, 0, sizeof(szString)); + hr = Installer_RegistryValueW(HKEY_CURRENT_USER, szKey, szOne, szString); + ok(SUCCEEDED(hr), "Installer_RegistryValueW failed, hresult 0x%08x\n", hr); + ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, szOne); + + /* Get string class name for the key */ + memset(szString, 0, sizeof(szString)); + hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, 0, szString, VT_BSTR); + ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr); + ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, szBlank); + + /* Get name of a value by positive number (RegEnumValue like), valid index */ + memset(szString, 0, sizeof(szString)); + hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, 2, szString, VT_BSTR); + ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr); + ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, szTwo); + + /* Get name of a value by positive number (RegEnumValue like), invalid index */ + memset(szString, 0, sizeof(szString)); + hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, 10, szString, VT_EMPTY); + ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr); + + /* Get name of a subkey by negative number (RegEnumValue like), valid index */ + memset(szString, 0, sizeof(szString)); + hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, -1, szString, VT_BSTR); + ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr); + ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, szFour); + + /* Get name of a subkey by negative number (RegEnumValue like), invalid index */ + memset(szString, 0, sizeof(szString)); + hr = Installer_RegistryValueI(HKEY_CURRENT_USER, szKey, -10, szString, VT_EMPTY); + ok(SUCCEEDED(hr), "Installer_RegistryValueI failed, hresult 0x%08x\n", hr); + } + + /* clean up */ + delete_key(hkey); +} + static void test_Installer(void) { + static WCHAR szProductCode[] = { '{','F','1','C','3','A','F','5','0','-','8','B','5','6','-','4','A','6','9','-','A','0','0','C','-','0','0','7','7','3','F','E','4','2','F','3','0','}',0 }; static WCHAR szBackslash[] = { '\\',0 }; WCHAR szPath[MAX_PATH]; HRESULT hr; UINT len; - IDispatch *pSession = NULL, *pRecord = NULL; + IDispatch *pSession = NULL, *pRecord = NULL, *pStringList = NULL; + int iState; if (!pInstaller) return; @@ -1028,6 +1275,51 @@ static void test_Installer(void) DeleteFileA(msifile); + /* Installer::RegistryValue */ + test_Installer_RegistryValue(); + + /* Installer::Products */ + hr = Installer_Products(&pStringList); + ok(SUCCEEDED(hr), "Installer_Products failed, hresult 0x%08x\n", hr); + if (SUCCEEDED(hr)) + { + int iCount = 0, idx; + + /* StringList::Count */ + hr = StringList_Count(pStringList, &iCount); + ok(SUCCEEDED(hr), "StringList_Count failed, hresult 0x%08x\n", hr); + + for (idx=0; idxoxid)); + /* Release the references to the registered class objects */ + COM_RevokeAllClasses(apt); + /* no locking is needed for this apartment, because no other thread * can access it at this point */ @@ -955,9 +959,6 @@ void WINAPI CoUninitialize(void) RunningObjectTableImpl_UnInitialize(); - /* Release the references to the registered class objects */ - COM_RevokeAllClasses(); - /* This will free the loaded COM Dlls */ CoFreeAllLibraries(); @@ -1582,6 +1583,7 @@ HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid) * reference count on this object. */ static HRESULT COM_GetRegisteredClassObject( + struct apartment *apt, REFCLSID rclsid, DWORD dwClsContext, LPUNKNOWN* ppUnk) @@ -1601,7 +1603,8 @@ static HRESULT COM_GetRegisteredClassObject( /* * Check if we have a match on the class ID and context. */ - if ((dwClsContext & curClass->runContext) && + if ((apt->oxid == curClass->apartment_id) && + (dwClsContext & curClass->runContext) && IsEqualGUID(&(curClass->classIdentifier), rclsid)) { /* @@ -1643,6 +1646,11 @@ static HRESULT COM_GetRegisteredClassObject( * SEE ALSO * CoRevokeClassObject, CoGetClassObject * + * NOTES + * In-process objects are only registered for the current apartment. + * CoGetClassObject() and CoCreateInstance() will not return objects registered + * in other apartments. + * * BUGS * MSDN claims that multiple interface registrations are legal, but we * can't do that with our current implementation. @@ -1657,6 +1665,7 @@ HRESULT WINAPI CoRegisterClassObject( RegisteredClass* newClass; LPUNKNOWN foundObject; HRESULT hr; + APARTMENT *apt; TRACE("(%s,%p,0x%08x,0x%08x,%p)\n", debugstr_guid(rclsid),pUnk,dwClsContext,flags,lpdwRegister); @@ -1664,7 +1673,8 @@ HRESULT WINAPI CoRegisterClassObject( if ( (lpdwRegister==0) || (pUnk==0) ) return E_INVALIDARG; - if (!COM_CurrentApt()) + apt = COM_CurrentApt(); + if (!apt) { ERR("COM was not initialized\n"); return CO_E_NOTINITIALIZED; @@ -1681,7 +1691,7 @@ HRESULT WINAPI CoRegisterClassObject( * First, check if the class is already registered. * If it is, this should cause an error. */ - hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject); + hr = COM_GetRegisteredClassObject(apt, rclsid, dwClsContext, &foundObject); if (hr == S_OK) { if (flags & REGCLS_MULTIPLEUSE) { if (dwClsContext & CLSCTX_LOCAL_SERVER) @@ -1699,6 +1709,7 @@ HRESULT WINAPI CoRegisterClassObject( return E_OUTOFMEMORY; newClass->classIdentifier = *rclsid; + newClass->apartment_id = apt->oxid; newClass->runContext = dwClsContext; newClass->connectFlags = flags; newClass->pMarshaledData = NULL; @@ -1745,6 +1756,44 @@ HRESULT WINAPI CoRegisterClassObject( return S_OK; } +static void COM_RevokeRegisteredClassObject(RegisteredClass *curClass) +{ + list_remove(&curClass->entry); + + if (curClass->runContext & CLSCTX_LOCAL_SERVER) + RPC_StopLocalServer(curClass->RpcRegistration); + + /* + * Release the reference to the class object. + */ + IUnknown_Release(curClass->classObject); + + if (curClass->pMarshaledData) + { + LARGE_INTEGER zero; + memset(&zero, 0, sizeof(zero)); + IStream_Seek(curClass->pMarshaledData, zero, STREAM_SEEK_SET, NULL); + CoReleaseMarshalData(curClass->pMarshaledData); + } + + HeapFree(GetProcessHeap(), 0, curClass); +} + +static void COM_RevokeAllClasses(struct apartment *apt) +{ + RegisteredClass *curClass, *cursor; + + EnterCriticalSection( &csRegisteredClassList ); + + LIST_FOR_EACH_ENTRY_SAFE(curClass, cursor, &RegisteredClassList, RegisteredClass, entry) + { + if (curClass->apartment_id == apt->oxid) + COM_RevokeRegisteredClassObject(curClass); + } + + LeaveCriticalSection( &csRegisteredClassList ); +} + /*********************************************************************** * CoRevokeClassObject [OLE32.@] * @@ -1757,6 +1806,10 @@ HRESULT WINAPI CoRegisterClassObject( * Success: S_OK. * Failure: HRESULT code. * + * NOTES + * Must be called from the same apartment that called CoRegisterClassObject(), + * otherwise it will fail with RPC_E_WRONG_THREAD. + * * SEE ALSO * CoRegisterClassObject */ @@ -1765,9 +1818,17 @@ HRESULT WINAPI CoRevokeClassObject( { HRESULT hr = E_INVALIDARG; RegisteredClass *curClass; + APARTMENT *apt; TRACE("(%08x)\n",dwRegister); + apt = COM_CurrentApt(); + if (!apt) + { + ERR("COM was not initialized\n"); + return CO_E_NOTINITIALIZED; + } + EnterCriticalSection( &csRegisteredClassList ); LIST_FOR_EACH_ENTRY(curClass, &RegisteredClassList, RegisteredClass, entry) @@ -1777,30 +1838,17 @@ HRESULT WINAPI CoRevokeClassObject( */ if (curClass->dwCookie == dwRegister) { - list_remove(&curClass->entry); - - if (curClass->runContext & CLSCTX_LOCAL_SERVER) - RPC_StopLocalServer(curClass->RpcRegistration); - - /* - * Release the reference to the class object. - */ - IUnknown_Release(curClass->classObject); - - if (curClass->pMarshaledData) + if (curClass->apartment_id == apt->oxid) { - LARGE_INTEGER zero; - memset(&zero, 0, sizeof(zero)); - IStream_Seek(curClass->pMarshaledData, zero, STREAM_SEEK_SET, NULL); - CoReleaseMarshalData(curClass->pMarshaledData); + COM_RevokeRegisteredClassObject(curClass); + hr = S_OK; + } + else + { + ERR("called from wrong apartment, should be called from %s\n", + wine_dbgstr_longlong(curClass->apartment_id)); + hr = RPC_E_WRONG_THREAD; } - - /* - * Free the memory used by the chain node. - */ - HeapFree(GetProcessHeap(), 0, curClass); - - hr = S_OK; break; } } @@ -1848,7 +1896,8 @@ static void get_threading_model(HKEY key, LPWSTR value, DWORD len) value[0] = '\0'; } -static HRESULT get_inproc_class_object(HKEY hkeydll, REFCLSID rclsid, REFIID riid, void **ppv) +static HRESULT get_inproc_class_object(APARTMENT *apt, HKEY hkeydll, + REFCLSID rclsid, REFIID riid, void **ppv) { static const WCHAR wszApartment[] = {'A','p','a','r','t','m','e','n','t',0}; static const WCHAR wszFree[] = {'F','r','e','e',0}; @@ -1856,7 +1905,6 @@ static HRESULT get_inproc_class_object(HKEY hkeydll, REFCLSID rclsid, REFIID rii WCHAR dllpath[MAX_PATH+1]; WCHAR threading_model[10 /* strlenW(L"apartment")+1 */]; HRESULT hr; - APARTMENT *apt = COM_CurrentApt(); get_threading_model(hkeydll, threading_model, ARRAYSIZE(threading_model)); /* "Apartment" */ @@ -1972,6 +2020,7 @@ HRESULT WINAPI CoGetClassObject( { LPUNKNOWN regClassObject; HRESULT hres = E_UNEXPECTED; + APARTMENT *apt; TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid), debugstr_guid(iid)); @@ -1980,7 +2029,8 @@ HRESULT WINAPI CoGetClassObject( *ppv = NULL; - if (!COM_CurrentApt()) + apt = COM_CurrentApt(); + if (!apt) { ERR("apartment not initialised\n"); return CO_E_NOTINITIALIZED; @@ -1995,7 +2045,8 @@ HRESULT WINAPI CoGetClassObject( * First, try and see if we can't match the class ID with one of the * registered classes. */ - if (S_OK == COM_GetRegisteredClassObject(rclsid, dwClsContext, ®ClassObject)) + if (S_OK == COM_GetRegisteredClassObject(apt, rclsid, dwClsContext, + ®ClassObject)) { /* Get the required interface from the retrieved pointer. */ hres = IUnknown_QueryInterface(regClassObject, iid, ppv); @@ -2024,13 +2075,16 @@ HRESULT WINAPI CoGetClassObject( { if (hres == REGDB_E_CLASSNOTREG) ERR("class %s not registered\n", debugstr_guid(rclsid)); - else + else if (hres == REGDB_E_KEYMISSING) + { WARN("class %s not registered as in-proc server\n", debugstr_guid(rclsid)); + hres = REGDB_E_CLASSNOTREG; + } } if (SUCCEEDED(hres)) { - hres = get_inproc_class_object(hkey, rclsid, iid, ppv); + hres = get_inproc_class_object(apt, hkey, rclsid, iid, ppv); RegCloseKey(hkey); } @@ -2051,13 +2105,16 @@ HRESULT WINAPI CoGetClassObject( { if (hres == REGDB_E_CLASSNOTREG) ERR("class %s not registered\n", debugstr_guid(rclsid)); - else + else if (hres == REGDB_E_KEYMISSING) + { WARN("class %s not registered in-proc handler\n", debugstr_guid(rclsid)); + hres = REGDB_E_CLASSNOTREG; + } } if (SUCCEEDED(hres)) { - hres = get_inproc_class_object(hkey, rclsid, iid, ppv); + hres = get_inproc_class_object(apt, hkey, rclsid, iid, ppv); RegCloseKey(hkey); } @@ -2378,20 +2435,6 @@ HRESULT WINAPI CoFileTimeNow( FILETIME *lpFileTime ) return S_OK; } -static void COM_RevokeAllClasses(void) -{ - EnterCriticalSection( &csRegisteredClassList ); - - while (list_head(&RegisteredClassList)) - { - RegisteredClass *curClass = LIST_ENTRY(list_head(&RegisteredClassList), - RegisteredClass, entry); - CoRevokeClassObject(curClass->dwCookie); - } - - LeaveCriticalSection( &csRegisteredClassList ); -} - /****************************************************************************** * CoLockObjectExternal [OLE32.@] * diff --git a/dlls/ole32/errorinfo.c b/dlls/ole32/errorinfo.c index 01dc30531ff..7318a970f3f 100644 --- a/dlls/ole32/errorinfo.c +++ b/dlls/ole32/errorinfo.c @@ -465,8 +465,18 @@ static const ISupportErrorInfoVtbl ISupportErrorInfoImpl_VTable = ISupportErrorInfoImpl_InterfaceSupportsErrorInfo }; + /*********************************************************************** * CreateErrorInfo (OLE32.@) + * + * Creates an object used to set details for an error info object. + * + * PARAMS + * pperrinfo [O]. Address where error info creation object will be stored. + * + * RETURNS + * Success: S_OK. + * Failure: HRESULT code. */ HRESULT WINAPI CreateErrorInfo(ICreateErrorInfo **pperrinfo) { @@ -483,6 +493,21 @@ HRESULT WINAPI CreateErrorInfo(ICreateErrorInfo **pperrinfo) /*********************************************************************** * GetErrorInfo (OLE32.@) + * + * Retrieves the error information object for the current thread. + * + * PARAMS + * dwReserved [I]. Reserved. Must be zero. + * pperrinfo [O]. Address where error information object will be stored on return. + * + * RETURNS + * Success: S_OK if an error information object was set for the current thread. + * S_FALSE if otherwise. + * Failure: E_INVALIDARG if dwReserved is not zero. + * + * NOTES + * This function causes the current error info object for the thread to be + * cleared if one was set beforehand. */ HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo) { @@ -511,6 +536,16 @@ HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo) /*********************************************************************** * SetErrorInfo (OLE32.@) + * + * Sets the error information object for the current thread. + * + * PARAMS + * dwReserved [I] Reserved. Must be zero. + * perrinfo [I] Error info object. + * + * RETURNS + * Success: S_OK. + * Failure: E_INVALIDARG if dwReserved is not zero. */ HRESULT WINAPI SetErrorInfo(ULONG dwReserved, IErrorInfo *perrinfo) { diff --git a/dlls/ole32/ole2.c b/dlls/ole32/ole2.c index 127ef876544..8ad9953daaf 100644 --- a/dlls/ole32/ole2.c +++ b/dlls/ole32/ole2.c @@ -149,7 +149,7 @@ extern void OLEClipbrd_Initialize(void); static void OLEDD_Initialize(void); static DropTargetNode* OLEDD_FindDropTarget( HWND hwndOfTarget); -static void OLEDD_FreeDropTarget(DropTargetNode*); +static void OLEDD_FreeDropTarget(DropTargetNode*, BOOL); static LRESULT WINAPI OLEDD_DragTrackerWindowProc( HWND hwnd, UINT uMsg, @@ -355,7 +355,7 @@ HRESULT WINAPI RevokeDragDrop( if (dropTargetInfo==NULL) return DRAGDROP_E_NOTREGISTERED; - OLEDD_FreeDropTarget(dropTargetInfo); + OLEDD_FreeDropTarget(dropTargetInfo, TRUE); return S_OK; } @@ -1896,10 +1896,10 @@ static void OLEDD_Initialize(void) * * Frees the drag and drop data structure */ -static void OLEDD_FreeDropTarget(DropTargetNode *dropTargetInfo) +static void OLEDD_FreeDropTarget(DropTargetNode *dropTargetInfo, BOOL release_drop_target) { list_remove(&dropTargetInfo->entry); - IDropTarget_Release(dropTargetInfo->dropTarget); + if (release_drop_target) IDropTarget_Release(dropTargetInfo->dropTarget); HeapFree(GetProcessHeap(), 0, dropTargetInfo); } @@ -1915,9 +1915,8 @@ void OLEDD_UnInitialize(void) */ while (!list_empty(&targetListHead)) { - DropTargetNode* curNode; - curNode = LIST_ENTRY(list_head(&targetListHead), DropTargetNode, entry); - OLEDD_FreeDropTarget(curNode); + DropTargetNode* curNode = LIST_ENTRY(list_head(&targetListHead), DropTargetNode, entry); + OLEDD_FreeDropTarget(curNode, FALSE); } } diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c index 43891e63ed2..12fe4f67e33 100644 --- a/dlls/ole32/tests/compobj.c +++ b/dlls/ole32/tests/compobj.c @@ -60,6 +60,12 @@ static const IID IID_IWineTest = 0x4fd0, {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */ +static const CLSID CLSID_WineOOPTest = { + 0x5201163f, + 0x8164, + 0x4fd0, + {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} +}; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */ static LONG cLocks; @@ -643,14 +649,9 @@ static void test_CoMarshalInterThreadInterfaceInStream(void) static void test_CoRegisterClassObject(void) { - static const CLSID CLSID_WineOOPTest = { - 0x5201163f, - 0x8164, - 0x4fd0, - {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} - }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */ DWORD cookie; HRESULT hr; + IClassFactory *pcf; pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); @@ -699,6 +700,192 @@ static void test_CoRegisterClassObject(void) hr = CoRevokeClassObject(cookie); ok_ole_success(hr, "CoRevokeClassObject"); + /* test whether registered class becomes invalid when apartment is destroyed */ + hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, + CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie); + ok_ole_success(hr, "CoRegisterClassObject"); + + CoUninitialize(); + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, NULL, + &IID_IClassFactory, (void **)&pcf); + ok(hr == REGDB_E_CLASSNOTREG, "object registered in an apartment shouldn't accessible after it is destroyed\n"); + + /* crashes with at least win9x DCOM! */ + if (0) + hr = CoRevokeClassObject(cookie); + + CoUninitialize(); +} + +static HRESULT get_class_object(CLSCTX clsctx) +{ + HRESULT hr; + IClassFactory *pcf; + + hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory, + (void **)&pcf); + + if (SUCCEEDED(hr)) + IClassFactory_Release(pcf); + + return hr; +} + +static DWORD CALLBACK get_class_object_thread(LPVOID pv) +{ + CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv; + HRESULT hr; + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + hr = get_class_object(clsctx); + + CoUninitialize(); + + return hr; +} + +static DWORD CALLBACK get_class_object_proxy_thread(LPVOID pv) +{ + CLSCTX clsctx = (CLSCTX)(DWORD_PTR)pv; + HRESULT hr; + IClassFactory *pcf; + IMultiQI *pMQI; + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + hr = CoGetClassObject(&CLSID_WineOOPTest, clsctx, NULL, &IID_IClassFactory, + (void **)&pcf); + + if (SUCCEEDED(hr)) + { + hr = IClassFactory_QueryInterface(pcf, &IID_IMultiQI, (void **)&pMQI); + if (SUCCEEDED(hr)) + IMultiQI_Release(pMQI); + IClassFactory_Release(pcf); + } + + CoUninitialize(); + + return hr; +} + +static DWORD CALLBACK register_class_object_thread(LPVOID pv) +{ + HRESULT hr; + DWORD cookie; + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, + CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie); + + CoUninitialize(); + + return hr; +} + +static DWORD CALLBACK revoke_class_object_thread(LPVOID pv) +{ + DWORD cookie = (DWORD_PTR)pv; + HRESULT hr; + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + hr = CoRevokeClassObject(cookie); + + CoUninitialize(); + + return hr; +} + +static void test_registered_object_thread_affinity(void) +{ + HRESULT hr; + DWORD cookie; + HANDLE thread; + DWORD tid; + DWORD exitcode; + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + /* CLSCTX_INPROC_SERVER */ + + hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, + CLSCTX_INPROC_SERVER, REGCLS_SINGLEUSE, &cookie); + ok_ole_success(hr, "CoRegisterClassObject"); + + thread = CreateThread(NULL, 0, get_class_object_thread, (LPVOID)CLSCTX_INPROC_SERVER, 0, &tid); + ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); + WaitForSingleObject(thread, INFINITE); + GetExitCodeThread(thread, &exitcode); + hr = exitcode; + ok(hr == REGDB_E_CLASSNOTREG, "CoGetClassObject on inproc object " + "registered in different thread should return REGDB_E_CLASSNOTREG " + "instead of 0x%08x\n", hr); + + hr = get_class_object(CLSCTX_INPROC_SERVER); + ok(hr == S_OK, "CoGetClassObject on inproc object registered in same " + "thread should return S_OK instead of 0x%08x\n", hr); + + thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid); + ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); + WaitForSingleObject(thread, INFINITE); + GetExitCodeThread(thread, &exitcode); + hr = exitcode; + ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different thread should return S_OK instead of 0x%08x\n", hr); + + hr = CoRevokeClassObject(cookie); + ok_ole_success(hr, "CoRevokeClassObject"); + + /* CLSCTX_LOCAL_SERVER */ + + hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&Test_ClassFactory, + CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &cookie); + ok_ole_success(hr, "CoRegisterClassObject"); + + thread = CreateThread(NULL, 0, get_class_object_proxy_thread, (LPVOID)CLSCTX_LOCAL_SERVER, 0, &tid); + ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); + while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0 + 1) + { + MSG msg; + while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + } + GetExitCodeThread(thread, &exitcode); + hr = exitcode; + ok(hr == S_OK, "CoGetClassObject on local server object " + "registered in different thread should return S_OK " + "instead of 0x%08x\n", hr); + + hr = get_class_object(CLSCTX_LOCAL_SERVER); + ok(hr == S_OK, "CoGetClassObject on local server object registered in same " + "thread should return S_OK instead of 0x%08x\n", hr); + + thread = CreateThread(NULL, 0, revoke_class_object_thread, (LPVOID)cookie, 0, &tid); + ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); + WaitForSingleObject(thread, INFINITE); + GetExitCodeThread(thread, &exitcode); + hr = exitcode; + ok(hr == RPC_E_WRONG_THREAD, "CoRevokeClassObject called from different " + "thread to where registered should return RPC_E_WRONG_THREAD instead of 0x%08x\n", hr); + + thread = CreateThread(NULL, 0, register_class_object_thread, NULL, 0, &tid); + ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError()); + WaitForSingleObject(thread, INFINITE); + GetExitCodeThread(thread, &exitcode); + hr = exitcode; + ok(hr == S_OK, "CoRegisterClassObject with same CLSID but in different " + "thread should return S_OK instead of 0x%08x\n", hr); + + hr = CoRevokeClassObject(cookie); + ok_ole_success(hr, "CoRevokeClassObject"); + CoUninitialize(); } @@ -775,5 +962,6 @@ START_TEST(compobj) test_CoMarshalInterface(); test_CoMarshalInterThreadInterfaceInStream(); test_CoRegisterClassObject(); + test_registered_object_thread_affinity(); test_CoFreeUnusedLibraries(); } diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index 91cad1d1f7d..a409b326ee6 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -29,6 +29,7 @@ #include #include #include +#include #include static HMODULE hmoduleRichEdit; diff --git a/dlls/rsaenh/rsaenh.c b/dlls/rsaenh/rsaenh.c index 2ace2d56b28..cfa230ceee0 100644 --- a/dlls/rsaenh/rsaenh.c +++ b/dlls/rsaenh/rsaenh.c @@ -1050,7 +1050,8 @@ static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTa KEYCONTAINER *pKeyContainer; HCRYPTPROV hKeyContainer; DATA_BLOB blobIn, blobOut; - + HCRYPTKEY hCryptKey; + sprintf(szRSABase, RSAENH_REGKEY, pszContainerName); if (dwFlags & CRYPT_MACHINE_KEYSET) { @@ -1089,8 +1090,9 @@ static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTa if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL, (dwFlags & CRYPT_MACHINE_KEYSET) ? CRYPTPROTECT_LOCAL_MACHINE : 0, &blobOut)) { - RSAENH_CPImportKey(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0, - &pKeyContainer->hKeyExchangeKeyPair); + if(RSAENH_CPImportKey(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0, + &hCryptKey)) + pKeyContainer->hKeyExchangeKeyPair = hCryptKey; HeapFree(GetProcessHeap(), 0, blobOut.pbData); } } @@ -1113,8 +1115,9 @@ static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTa if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL, (dwFlags & CRYPT_MACHINE_KEYSET) ? CRYPTPROTECT_LOCAL_MACHINE : 0, &blobOut)) { - RSAENH_CPImportKey(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0, - &pKeyContainer->hSignatureKeyPair); + if(RSAENH_CPImportKey(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0, + &hCryptKey)) + pKeyContainer->hSignatureKeyPair = hCryptKey; HeapFree(GetProcessHeap(), 0, blobOut.pbData); } } @@ -1473,7 +1476,12 @@ BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer, SetLastError(NTE_BAD_KEYSET_PARAM); return FALSE; } else { - if (!RegDeleteKeyA(HKEY_CURRENT_USER, szRegKey)) { + HKEY hRootKey; + if (dwFlags & CRYPT_MACHINE_KEYSET) + hRootKey = HKEY_LOCAL_MACHINE; + else + hRootKey = HKEY_CURRENT_USER; + if (!RegDeleteKeyA(hRootKey, szRegKey)) { SetLastError(ERROR_SUCCESS); return TRUE; } else { diff --git a/dlls/rsaenh/tests/rsaenh.c b/dlls/rsaenh/tests/rsaenh.c index fe27f4bd449..b51a0a526ee 100644 --- a/dlls/rsaenh/tests/rsaenh.c +++ b/dlls/rsaenh/tests/rsaenh.c @@ -1603,6 +1603,46 @@ static void test_null_provider(void) CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET); + + + /* test for the bug in accessing the user key in a container + */ + result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, + CRYPT_NEWKEYSET); + ok(result, "CryptAcquireContext failed: %08x\n", GetLastError()); + result = CryptGenKey(prov, AT_KEYEXCHANGE, 0, &key); + ok(result, "CryptGenKey with AT_KEYEXCHANGE failed with error %08x\n", GetLastError()); + CryptDestroyKey(key); + CryptReleaseContext(prov,0); + result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,0); + ok(result, "CryptAcquireContext failed: 0x%08x\n", GetLastError()); + result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key); + ok (result, "CryptGetUserKey failed with error %08x\n", GetLastError()); + CryptDestroyKey(key); + + CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, + CRYPT_DELETEKEYSET); + + /* test the machine key set */ + CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, + CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET); + result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, + CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET); + ok(result, "CryptAcquireContext with CRYPT_MACHINE_KEYSET failed: %08x\n", GetLastError()); + CryptReleaseContext(prov, 0); + result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, + CRYPT_MACHINE_KEYSET); + ok(result, "CryptAcquireContext with CRYPT_MACHINE_KEYSET failed: %08x\n", GetLastError()); + CryptReleaseContext(prov,0); + result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, + CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET); + ok(result, "CryptAcquireContext with CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET failed: %08x\n", + GetLastError()); + result = CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL, + CRYPT_MACHINE_KEYSET); + ok(!result && GetLastError() == NTE_BAD_KEYSET , + "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError()); + } START_TEST(rsaenh) diff --git a/dlls/setupapi/misc.c b/dlls/setupapi/misc.c index b79c0e68034..2a91b1781c7 100644 --- a/dlls/setupapi/misc.c +++ b/dlls/setupapi/misc.c @@ -919,6 +919,29 @@ done: return ret; } +static int compare_files( HANDLE file1, HANDLE file2 ) +{ + char buffer1[2048]; + char buffer2[2048]; + DWORD size1; + DWORD size2; + + while( ReadFile(file1, buffer1, sizeof(buffer1), &size1, NULL) && + ReadFile(file2, buffer2, sizeof(buffer2), &size2, NULL) ) + { + int ret; + if (size1 != size2) + return size1 > size2 ? 1 : -1; + if (!size1) + return 0; + ret = memcmp( buffer1, buffer2, size1 ); + if (ret) + return ret; + } + + return 0; +} + /*********************************************************************** * SetupCopyOEMInfW (SETUPAPI.@) */ @@ -959,6 +982,20 @@ BOOL WINAPI SetupCopyOEMInfW( PCWSTR source, PCWSTR location, { static const WCHAR oem[] = { 'o','e','m',0 }; unsigned int i; + LARGE_INTEGER source_file_size; + HANDLE source_file; + + source_file = CreateFileW( source, FILE_READ_DATA | FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, 0, NULL ); + if (source_file == INVALID_HANDLE_VALUE) + return FALSE; + + if (!GetFileSizeEx( source_file, &source_file_size )) + { + CloseHandle( source_file ); + return FALSE; + } p = strrchrW( target, '\\' ) + 1; memcpy( p, oem, sizeof(oem) ); @@ -968,12 +1005,30 @@ BOOL WINAPI SetupCopyOEMInfW( PCWSTR source, PCWSTR location, for (i = 0; i < OEM_INDEX_LIMIT; i++) { static const WCHAR format[] = { '%','u','.','i','n','f',0 }; + HANDLE dest_file; + LARGE_INTEGER dest_file_size; + wsprintfW( p, format, i ); + dest_file = CreateFileW( target, FILE_READ_DATA | FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, 0, NULL ); /* if we found a file name that doesn't exist then we're done */ - if (GetFileAttributesW( target ) == INVALID_FILE_ATTRIBUTES) + if (dest_file == INVALID_HANDLE_VALUE) break; + /* now check if the same inf file has already been copied to the inf + * directory. if so, use that file and don't create a new one */ + if (!GetFileSizeEx( dest_file, &dest_file_size ) || + (dest_file_size.QuadPart != source_file_size.QuadPart) || + compare_files( source_file, dest_file )) + { + CloseHandle( dest_file ); + continue; + } + CloseHandle( dest_file ); + break; } + CloseHandle( source_file ); if (i == OEM_INDEX_LIMIT) { SetLastError( ERROR_FILENAME_EXCED_RANGE ); diff --git a/dlls/setupapi/query.c b/dlls/setupapi/query.c index 19613751d18..cd50deee592 100644 --- a/dlls/setupapi/query.c +++ b/dlls/setupapi/query.c @@ -652,8 +652,12 @@ BOOL WINAPI SetupQueryInfOriginalFileInformationW( PSP_ORIGINAL_FILE_INFO_W OriginalFileInfo) { LPCWSTR inf_name; + LPCWSTR inf_path; + HINF hinf; + static const WCHAR wszVersion[] = { 'V','e','r','s','i','o','n',0 }; + static const WCHAR wszCatalogFile[] = { 'C','a','t','a','l','o','g','F','i','l','e',0 }; - FIXME("(%p, %d, %p, %p): stub\n", InfInformation, InfIndex, + FIXME("(%p, %d, %p, %p): semi-stub\n", InfInformation, InfIndex, AlternativePlatformInfo, OriginalFileInfo); if (OriginalFileInfo->cbSize != sizeof(*OriginalFileInfo)) @@ -662,18 +666,30 @@ BOOL WINAPI SetupQueryInfOriginalFileInformationW( return ERROR_INVALID_USER_BUFFER; } + inf_path = (LPWSTR)&InfInformation->VersionData[0]; + /* FIXME: we should get OriginalCatalogName from CatalogFile line in * the original inf file and cache it, but that would require building a * .pnf file. */ - OriginalFileInfo->OriginalCatalogName[0] = '\0'; + hinf = SetupOpenInfFileW(inf_path, NULL, INF_STYLE_WIN4, NULL); + if (!hinf) return FALSE; + + if (!SetupGetLineTextW(NULL, hinf, wszVersion, wszCatalogFile, + OriginalFileInfo->OriginalCatalogName, + sizeof(OriginalFileInfo->OriginalCatalogName)/sizeof(OriginalFileInfo->OriginalCatalogName[0]), + NULL)) + { + OriginalFileInfo->OriginalCatalogName[0] = '\0'; + } + SetupCloseInfFile(hinf); /* FIXME: not quite correct as we just return the same file name as * destination (copied) inf file, not the source (original) inf file. * to fix it properly would require building a .pnf file */ /* file name is stored in VersionData field of InfInformation */ - inf_name = strrchrW((LPWSTR)&InfInformation->VersionData[0], '\\'); + inf_name = strrchrW(inf_path, '\\'); if (inf_name) inf_name++; - else inf_name = (LPWSTR)&InfInformation->VersionData[0]; + else inf_name = inf_path; strcpyW(OriginalFileInfo->OriginalInfName, inf_name); diff --git a/dlls/setupapi/tests/misc.c b/dlls/setupapi/tests/misc.c index 84b1ce17ab6..1c193e1f024 100644 --- a/dlls/setupapi/tests/misc.c +++ b/dlls/setupapi/tests/misc.c @@ -44,7 +44,7 @@ static CHAR CURR_DIR[MAX_PATH]; static BOOL (WINAPI *pSetupGetFileCompressionInfoExA)(PCSTR, PSTR, DWORD, PDWORD, PDWORD, PDWORD, PUINT); static BOOL (WINAPI *pSetupCopyOEMInfA)(PCSTR, PCSTR, DWORD, DWORD, PSTR, DWORD, PDWORD, PSTR *); - +static BOOL (WINAPI *pSetupQueryInfOriginalFileInformationA)(PSP_INF_INFORMATION, UINT, PSP_ALTPLATFORM_INFO, PSP_ORIGINAL_FILE_INFO_A); static void append_str(char **str, const char *data) { @@ -111,6 +111,12 @@ static void test_original_file_name(LPCSTR original, LPCSTR dest) BOOL res; DWORD size; + if (!pSetupQueryInfOriginalFileInformationA) + { + skip("SetupQueryInfOriginalFileInformationA is not available\n"); + return; + } + hinf = SetupOpenInfFileA(dest, NULL, INF_STYLE_WIN4, NULL); ok(hinf != NULL, "SetupOpenInfFileA failed with error %d\n", GetLastError()); @@ -123,12 +129,12 @@ static void test_original_file_name(LPCSTR original, LPCSTR dest) ok(res, "SetupGetInfInformation failed with error %d\n", GetLastError()); spofi.cbSize = 0; - res = SetupQueryInfOriginalFileInformationA(pspii, 0, NULL, &spofi); + res = pSetupQueryInfOriginalFileInformationA(pspii, 0, NULL, &spofi); ok(!res && GetLastError() == ERROR_INVALID_USER_BUFFER, "SetupQueryInfOriginalFileInformationA should have failed with ERROR_INVALID_USER_BUFFER instead of %d\n", GetLastError()); spofi.cbSize = sizeof(spofi); - res = SetupQueryInfOriginalFileInformationA(pspii, 0, NULL, &spofi); + res = pSetupQueryInfOriginalFileInformationA(pspii, 0, NULL, &spofi); ok(res, "SetupQueryInfOriginalFileInformationA failed with error %d\n", GetLastError()); ok(!spofi.OriginalCatalogName[0], "spofi.OriginalCatalogName should have been \"\" instead of \"%s\"\n", spofi.OriginalCatalogName); todo_wine @@ -568,6 +574,7 @@ START_TEST(misc) pSetupGetFileCompressionInfoExA = (void*)GetProcAddress(hsetupapi, "SetupGetFileCompressionInfoExA"); pSetupCopyOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupCopyOEMInfA"); + pSetupQueryInfOriginalFileInformationA = (void*)GetProcAddress(hsetupapi, "SetupQueryInfOriginalFileInformationA"); GetCurrentDirectoryA(MAX_PATH, CURR_DIR); diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c index 3acd37a05ba..ad729d0c377 100644 --- a/dlls/user32/dialog.c +++ b/dlls/user32/dialog.c @@ -651,7 +651,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate, if (unicode) SetWindowLongPtrW( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc ); else SetWindowLongPtrA( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc ); - if (dlgInfo->hUserFont) + if (dlgProc && dlgInfo->hUserFont) SendMessageW( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 ); /* Create controls */ @@ -660,13 +660,16 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate, { /* Send initialisation messages and set focus */ - if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ) && - ((~template.style & DS_CONTROL) || (template.style & WS_VISIBLE))) + if (dlgProc) { - /* By returning TRUE, app has requested a default focus assignment */ - dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE); - if( dlgInfo->hwndFocus ) - SetFocus( dlgInfo->hwndFocus ); + if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ) && + ((~template.style & DS_CONTROL) || (template.style & WS_VISIBLE))) + { + /* By returning TRUE, app has requested a default focus assignment */ + dlgInfo->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE); + if( dlgInfo->hwndFocus ) + SetFocus( dlgInfo->hwndFocus ); + } } if (template.style & WS_VISIBLE && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index a6daf8263eb..b40f6784e10 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -207,7 +207,7 @@ static const struct message WmSWP_ResizeNoZOrder[] = { { WM_NCCALCSIZE, sent|wparam, 1 }, { WM_NCPAINT, sent }, { WM_GETTEXT, sent|defwinproc|optional }, - { WM_ERASEBKGND, sent|parent|optional }, /* FIXME: remove optional once Wine is fixed */ + { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ { WM_WINDOWPOSCHANGED, sent|wparam, /*SWP_NOZORDER|*/SWP_NOMOVE|SWP_NOCLIENTMOVE }, { WM_SIZE, sent|defwinproc|wparam, 0 }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ @@ -6321,6 +6321,7 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) !lstrcmpiA(buf, "my_button_class") || !lstrcmpiA(buf, "my_edit_class") || !lstrcmpiA(buf, "static") || + !lstrcmpiA(buf, "MyDialogClass") || !lstrcmpiA(buf, "#32770")) { struct message msg; @@ -6367,6 +6368,7 @@ static void CALLBACK win_event_proc(HWINEVENTHOOK hevent, !lstrcmpiA(buf, "my_button_class") || !lstrcmpiA(buf, "my_edit_class") || !lstrcmpiA(buf, "static") || + !lstrcmpiA(buf, "MyDialogClass") || !lstrcmpiA(buf, "#32770")) { struct message msg; @@ -8874,6 +8876,56 @@ static void test_ShowWindow(void) DestroyWindow(hwnd); } +static INT_PTR WINAPI test_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + struct message msg; + + trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam); + + switch (message) + { + case WM_WINDOWPOSCHANGING: + case WM_WINDOWPOSCHANGED: + { + WINDOWPOS *winpos = (WINDOWPOS *)lParam; + + trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED"); + trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", + winpos->hwnd, winpos->hwndInsertAfter, + winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); + dump_winpos_flags(winpos->flags); + + /* Log only documented flags, win2k uses 0x1000 and 0x2000 + * in the high word for internal purposes + */ + wParam = winpos->flags & 0xffff; + /* We are not interested in the flags that don't match under XP and Win9x */ + wParam &= ~(SWP_NOZORDER); + break; + } + + /* explicitly ignore WM_GETICON message */ + case WM_GETICON: + return 0; + } + + msg.message = message; + msg.flags = sent|wparam|lparam; + msg.wParam = wParam; + msg.lParam = lParam; + add_message(&msg); + + /* calling DefDlgProc leads to a recursion under XP */ + + switch (message) + { + case WM_INITDIALOG: + case WM_GETDLGCODE: + return 0; + } + return 1; +} + static const struct message WmDefDlgSetFocus_1[] = { { WM_GETDLGCODE, sent|wparam|lparam, 0, 0 }, { WM_GETTEXTLENGTH, sent|wparam|lparam|optional, 0, 0 }, /* XP */ @@ -8898,11 +8950,39 @@ static const struct message WmDefDlgSetFocus_2[] = { { WM_GETTEXT, sent|wparam|optional, 6 }, /* XP */ { WM_GETTEXT, sent|wparam|optional, 12 }, /* XP */ { EM_SETSEL, sent|wparam, 0 }, /* XP sets lparam to text length, Win9x to -2 */ + { WM_CTLCOLOREDIT, sent|optional }, /* XP */ + { 0 } +}; +/* Creation of a dialog */ +static const struct message WmCreateDialogParamSeq_1[] = { + { HCBT_CREATEWND, hook }, + { WM_NCCREATE, sent }, + { WM_NCCALCSIZE, sent|wparam, 0 }, + { WM_CREATE, sent }, + { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_SIZE, sent|wparam, SIZE_RESTORED }, + { WM_MOVE, sent }, + { WM_SETFONT, sent }, + { WM_INITDIALOG, sent }, + { WM_CHANGEUISTATE, sent|optional }, + { 0 } +}; +/* Creation of a dialog */ +static const struct message WmCreateDialogParamSeq_2[] = { + { HCBT_CREATEWND, hook }, + { WM_NCCREATE, sent }, + { WM_NCCALCSIZE, sent|wparam, 0 }, + { WM_CREATE, sent }, + { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_SIZE, sent|wparam, SIZE_RESTORED }, + { WM_MOVE, sent }, + { WM_CHANGEUISTATE, sent|optional }, { 0 } }; static void test_dialog_messages(void) { + WNDCLASS cls; HWND hdlg, hedit1, hedit2, hfocus; LRESULT ret; @@ -8973,9 +9053,31 @@ static void test_dialog_messages(void) check_selection(hedit2, 0, 3); EndDialog(hdlg, 0); + flush_sequence(); #undef set_selection #undef check_selection + + ok(GetClassInfo(0, "#32770", &cls), "GetClassInfo failed\n"); + cls.lpszClassName = "MyDialogClass"; + cls.hInstance = GetModuleHandle(0); + /* need a cast since a dlgproc is used as a wndproc */ + cls.lpfnWndProc = (WNDPROC)test_dlg_proc; + if (!RegisterClass(&cls)) assert(0); + + hdlg = CreateDialogParam(0, "CLASS_TEST_DIALOG_2", 0, test_dlg_proc, 0); + ok(IsWindow(hdlg), "CreateDialogParam failed\n"); + ok_sequence(WmCreateDialogParamSeq_1, "CreateDialogParam_1", FALSE); + EndDialog(hdlg, 0); + flush_sequence(); + + hdlg = CreateDialogParam(0, "CLASS_TEST_DIALOG_2", 0, NULL, 0); + ok(IsWindow(hdlg), "CreateDialogParam failed\n"); + ok_sequence(WmCreateDialogParamSeq_2, "CreateDialogParam_2", FALSE); + EndDialog(hdlg, 0); + flush_sequence(); + + UnregisterClass(cls.lpszClassName, cls.hInstance); } static void test_nullCallback(void) diff --git a/dlls/user32/tests/resource.rc b/dlls/user32/tests/resource.rc index 8434f6102ee..47328fc7d4f 100644 --- a/dlls/user32/tests/resource.rc +++ b/dlls/user32/tests/resource.rc @@ -72,6 +72,14 @@ FONT 8, "MS Shell Dlg" { } +CLASS_TEST_DIALOG_2 DIALOG DISCARDABLE 0, 0, 100, 100 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "CreateDialogParams Test" +CLASS "MyDialogClass" +FONT 8, "MS Shell Dlg" +{ +} + FOCUS_TEST_DIALOG DIALOG DISCARDABLE 0, 0, 60, 30 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CONTROL CAPTION "Test dialog" diff --git a/dlls/wined3d/Makefile.in b/dlls/wined3d/Makefile.in index 4700483d245..b08b050d151 100644 --- a/dlls/wined3d/Makefile.in +++ b/dlls/wined3d/Makefile.in @@ -12,6 +12,7 @@ C_SRCS = \ arb_program_shader.c \ baseshader.c \ basetexture.c \ + clipper.c \ context.c \ cubetexture.c \ device.c \ diff --git a/dlls/wined3d/clipper.c b/dlls/wined3d/clipper.c new file mode 100644 index 00000000000..75bbbd00d96 --- /dev/null +++ b/dlls/wined3d/clipper.c @@ -0,0 +1,203 @@ +/* IWineD3DClipper implementation + * + * Copyright 2000 (c) Marcus Meissner + * Copyright 2000 (c) TransGaming Technologies Inc. + * Copyright 2006 (c) Stefan Dösinger + * + * 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 +#ifdef HAVE_FLOAT_H +# include +#endif +#include "wined3d_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d); + +static HRESULT WINAPI IWineD3DClipperImpl_QueryInterface(IWineD3DClipper *iface, REFIID riid, void **Obj) +{ + IWineD3DClipperImpl *This = (IWineD3DClipperImpl *)iface; + + TRACE("(%p)->(%p,%p)\n", This, riid, Obj); + if (IsEqualGUID(&IID_IUnknown, riid) + || IsEqualGUID(&IID_IWineD3DClipper, riid)) + { + *Obj = iface; + IWineD3DClipper_AddRef(iface); + return S_OK; + } + else + { + return E_NOINTERFACE; + } +} + +static ULONG WINAPI IWineD3DClipperImpl_AddRef(IWineD3DClipper *iface ) +{ + IWineD3DClipperImpl *This = (IWineD3DClipperImpl *)iface; + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p)->() incrementing from %u.\n", This, ref - 1); + + return ref; +} + +static ULONG WINAPI IWineD3DClipperImpl_Release(IWineD3DClipper *iface) +{ + IWineD3DClipperImpl *This = (IWineD3DClipperImpl *)iface; + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p)->() decrementing from %u.\n", This, ref + 1); + + if (ref == 0) + { + HeapFree(GetProcessHeap(), 0, This); + return 0; + } + else return ref; +} + +static HRESULT WINAPI IWineD3DClipperImpl_GetParent(IWineD3DClipper *iface, IUnknown **Parent) +{ + IWineD3DClipperImpl *This = (IWineD3DClipperImpl *)iface; + TRACE("(%p)->(%p)\n", This, Parent); + + *Parent = This->Parent; + IUnknown_AddRef(*Parent); + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DClipperImpl_SetHwnd(IWineD3DClipper *iface, DWORD Flags, HWND hWnd) +{ + IWineD3DClipperImpl *This = (IWineD3DClipperImpl *)iface; + + TRACE("(%p)->(0x%08x,%p)\n", This, Flags, hWnd); + if( Flags ) + { + FIXME("Flags = 0x%08x, not supported.\n",Flags); + return WINED3DERR_INVALIDCALL; + } + + This->hWnd = hWnd; + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DClipperImpl_GetClipList(IWineD3DClipper *iface, RECT *Rect, RGNDATA *ClipList, DWORD *Size) +{ + IWineD3DClipperImpl *This = (IWineD3DClipperImpl *)iface; + TRACE("(%p,%p,%p,%p)\n", This, Rect, ClipList, Size); + + if (This->hWnd) + { + HDC hDC = GetDCEx(This->hWnd, NULL, DCX_WINDOW); + if (hDC) + { + HRGN hRgn = CreateRectRgn(0,0,0,0); + if (GetRandomRgn(hDC, hRgn, SYSRGN)) + { + if (GetVersion() & 0x80000000) + { + /* map region to screen coordinates */ + POINT org; + GetDCOrgEx( hDC, &org ); + OffsetRgn( hRgn, org.x, org.y ); + } + if (Rect) + { + HRGN hRgnClip = CreateRectRgn(Rect->left, Rect->top, + Rect->right, Rect->bottom); + CombineRgn(hRgn, hRgn, hRgnClip, RGN_AND); + DeleteObject(hRgnClip); + } + *Size = GetRegionData(hRgn, *Size, ClipList); + } + DeleteObject(hRgn); + ReleaseDC(This->hWnd, hDC); + } + return WINED3D_OK; + } + else + { + static int warned = 0; + if (warned++ < 10) + FIXME("(%p,%p,%p,%p),stub!\n",This,Rect,ClipList,Size); + if (Size) *Size=0; + return WINEDDERR_NOCLIPLIST; + } +} + +static HRESULT WINAPI IWineD3DClipperImpl_SetClipList(IWineD3DClipper *iface, RGNDATA *rgn, DWORD Flags) +{ + IWineD3DClipperImpl *This = (IWineD3DClipperImpl *)iface; + static int warned = 0; + + if (warned++ < 10 || rgn == NULL) + FIXME("(%p,%p,%d),stub!\n",This,rgn,Flags); + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DClipperImpl_GetHwnd(IWineD3DClipper *iface, HWND *hwnd) +{ + IWineD3DClipperImpl *This = (IWineD3DClipperImpl *)iface; + TRACE("(%p)->(%p)\n", This, hwnd); + + *hwnd = This->hWnd; + return WINED3D_OK; +} + +static HRESULT WINAPI IWineD3DClipperImpl_IsClipListChanged(IWineD3DClipper *iface, BOOL *changed) +{ + IWineD3DClipperImpl *This = (IWineD3DClipperImpl *)iface; + FIXME("(%p)->(%p),stub!\n",This,changed); + + /* XXX What is safest? */ + *changed = FALSE; + + return WINED3D_OK; +} + +static const IWineD3DClipperVtbl IWineD3DClipper_Vtbl = +{ + IWineD3DClipperImpl_QueryInterface, + IWineD3DClipperImpl_AddRef, + IWineD3DClipperImpl_Release, + IWineD3DClipperImpl_GetParent, + IWineD3DClipperImpl_GetClipList, + IWineD3DClipperImpl_GetHwnd, + IWineD3DClipperImpl_IsClipListChanged, + IWineD3DClipperImpl_SetClipList, + IWineD3DClipperImpl_SetHwnd +}; + +IWineD3DClipper* WINAPI WineDirect3DCreateClipper(IUnknown *Parent) +{ + IWineD3DClipperImpl *obj; + + TRACE("Creating clipper, parent %p\n", Parent); + obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj)); + if(!obj) + { + ERR("Out of memory when trying to allocate a WineD3D Clipper\n"); + return NULL; + } + + obj->lpVtbl = &IWineD3DClipper_Vtbl; + obj->Parent = Parent; + + IWineD3DClipper_AddRef((IWineD3DClipper *)obj); + return (IWineD3DClipper *) obj; +} diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 5796393ab8b..3964bf2ed08 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -3838,7 +3838,7 @@ process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCo static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexDeclaration* pVertexDecl, DWORD Flags) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; WineDirect3DVertexStridedData strided; - BOOL vbo = FALSE; + BOOL vbo = FALSE, streamWasUP = This->stateBlock->streamIsUP; TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags); if(pVertexDecl) { @@ -3854,12 +3854,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, LEAVE_GL(); } + /* ProcessVertices reads from vertex buffers, which have to be assigned. DrawPrimitive and DrawPrimitiveUP + * control the streamIsUP flag, thus restore it afterwards. + */ + This->stateBlock->streamIsUP = FALSE; memset(&strided, 0, sizeof(strided)); if(This->stateBlock->vertexDecl) { primitiveDeclarationConvertToStridedData(iface, FALSE, &strided, &vbo); } else { primitiveConvertToStridedData(iface, &strided, &vbo); } + This->stateBlock->streamIsUP = streamWasUP; if(vbo || SrcStartIndex) { unsigned int i; diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 65a14d31ae1..9829f22bc9a 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1662,6 +1662,8 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN one often used by application to prevent the nice purple borders when bi-linear filtering is on */ table[i][3] = 0x00; + } else if(pal->Flags & WINEDDPCAPS_ALPHA) { + table[i][3] = pal->palents[i].peFlags; } else { table[i][3] = 0xFF; } @@ -1807,6 +1809,8 @@ static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES conve one often used by application to prevent the nice purple borders when bi-linear filtering is on */ table[i][3] = 0x00; + } else if(pal->Flags & WINEDDPCAPS_ALPHA) { + table[i][3] = pal->palents[i].peFlags; } else { table[i][3] = 0xFF; } @@ -2605,7 +2609,6 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice; IWineD3DSwapChainImpl *srcSwapchain = NULL, *dstSwapchain = NULL; IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface; - BOOL SrcOK = TRUE; TRACE("(%p)->(%p,%p,%p,%08x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx); @@ -2644,58 +2647,102 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT * } /* The only case where both surfaces on a swapchain are supported is a back buffer -> front buffer blit on the same swapchain */ - if(dstSwapchain && dstSwapchain == srcSwapchain) { + if(dstSwapchain && dstSwapchain == srcSwapchain && dstSwapchain->backBuffer && + ((IWineD3DSurface *) This == dstSwapchain->frontBuffer) && SrcSurface == dstSwapchain->backBuffer[0]) { /* Half-life does a Blt from the back buffer to the front buffer, * Full surface size, no flags... Use present instead + * + * This path will only be entered for d3d7 and ddraw apps, because d3d8/9 offer no way to blit TO the front buffer */ /* Check rects - IWineD3DDevice_Present doesn't handle them */ - if( SrcRect ) { - if( (SrcRect->left == 0) && (SrcRect->top == 0) && - (SrcRect->right == Src->currentDesc.Width) && (SrcRect->bottom == Src->currentDesc.Height) ) { - SrcOK = TRUE; + while(1) + { + RECT mySrcRect; + TRACE("Looking if a Present can be done... "); + /* Source Rectangle must be full surface */ + if( SrcRect ) { + if(SrcRect->left != 0 || SrcRect->top != 0 || + SrcRect->right != Src->currentDesc.Width || SrcRect->bottom != Src->currentDesc.Height) { + TRACE("No, Source rectangle doesn't match\n"); + break; + } + } + mySrcRect.left = 0; + mySrcRect.top = 0; + mySrcRect.right = Src->currentDesc.Width; + mySrcRect.bottom = Src->currentDesc.Height; + + /* No stretching may occur */ + if(mySrcRect.right != rect.x2 - rect.x1 || + mySrcRect.bottom != rect.y2 - rect.y1) { + TRACE("No, stretching is done\n"); + break; } - } else { - SrcOK = TRUE; - } - - /* Check the Destination rect and the surface sizes */ - if(SrcOK && - (rect.x1 == 0) && (rect.y1 == 0) && - (rect.x2 == This->currentDesc.Width) && (rect.y2 == This->currentDesc.Height) && - (This->currentDesc.Width == Src->currentDesc.Width) && - (This->currentDesc.Height == Src->currentDesc.Height)) { - /* These flags are unimportant for the flag check, remove them */ - - if((Flags & ~(WINEDDBLT_DONOTWAIT | WINEDDBLT_WAIT)) == 0) { - if( dstSwapchain->backBuffer && ((IWineD3DSurface *) This == dstSwapchain->frontBuffer) && - SrcSurface == dstSwapchain->backBuffer[0] ) { - - WINED3DSWAPEFFECT orig_swap = dstSwapchain->presentParms.SwapEffect; - - /* The idea behind this is that a glReadPixels and a glDrawPixels call - * take very long, while a flip is fast. - * This applies to Half-Life, which does such Blts every time it finished - * a frame, and to Prince of Persia 3D, which uses this to draw at least the main - * menu. This is also used by all apps when they do windowed rendering - * - * The problem is that flipping is not really the same as copying. After a - * Blt the front buffer is a copy of the back buffer, and the back buffer is - * untouched. Therefore it's necessary to override the swap effect - * and to set it back after the flip. - */ - - dstSwapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY; - TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n"); - IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice, - NULL, NULL, 0, NULL); + /* Destination must be full surface or match the clipping rectangle */ + if(This->clipper && ((IWineD3DClipperImpl *) This->clipper)->hWnd) + { + RECT cliprect; + POINT pos[2]; + GetClientRect(((IWineD3DClipperImpl *) This->clipper)->hWnd, &cliprect); + pos[0].x = rect.x1; + pos[0].y = rect.y1; + pos[1].x = rect.x2; + pos[1].y = rect.y2; + MapWindowPoints(GetDesktopWindow(), ((IWineD3DClipperImpl *) This->clipper)->hWnd, + pos, 2); + + if(pos[0].x != cliprect.left || pos[0].y != cliprect.top || + pos[1].x != cliprect.right || pos[1].y != cliprect.bottom) + { + TRACE("No, dest rectangle doesn't match(clipper)\n"); + TRACE("Clip rect at (%d,%d)-(%d,%d)\n", cliprect.left, cliprect.top, cliprect.right, cliprect.bottom); + TRACE("Blt dest: (%d,%d)-(%d,%d)\n", rect.x1, rect.y1, rect.x2, rect.y2); + break; + } + } + else + { + if(rect.x1 != 0 || rect.y1 != 0 || + rect.x2 != This->currentDesc.Width || rect.y2 != This->currentDesc.Height) { + TRACE("No, dest rectangle doesn't match(surface size)\n"); + break; + } + } - dstSwapchain->presentParms.SwapEffect = orig_swap; + TRACE("Yes\n"); - return WINED3D_OK; - } + /* These flags are unimportant for the flag check, remove them */ + if((Flags & ~(WINEDDBLT_DONOTWAIT | WINEDDBLT_WAIT)) == 0) { + WINED3DSWAPEFFECT orig_swap = dstSwapchain->presentParms.SwapEffect; + + /* The idea behind this is that a glReadPixels and a glDrawPixels call + * take very long, while a flip is fast. + * This applies to Half-Life, which does such Blts every time it finished + * a frame, and to Prince of Persia 3D, which uses this to draw at least the main + * menu. This is also used by all apps when they do windowed rendering + * + * The problem is that flipping is not really the same as copying. After a + * Blt the front buffer is a copy of the back buffer, and the back buffer is + * untouched. Therefore it's necessary to override the swap effect + * and to set it back after the flip. + * + * Windowed Direct3D < 7 apps do the same. The D3D7 sdk demso are nice + * testcases. + */ + + dstSwapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY; + + TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n"); + IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice, + NULL, NULL, 0, NULL); + + dstSwapchain->presentParms.SwapEffect = orig_swap; + + return WINED3D_OK; } + break; } TRACE("Unsupported blit between buffers on the same swapchain\n"); @@ -3419,6 +3466,25 @@ HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *S return WINED3D_OK; } +HRESULT WINAPI IWineD3DSurfaceImpl_SetClipper(IWineD3DSurface *iface, IWineD3DClipper *clipper) +{ + IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + TRACE("(%p)->(%p)\n", This, clipper); + + This->clipper = clipper; + return WINED3D_OK; +} + +HRESULT WINAPI IWineD3DSurfaceImpl_GetClipper(IWineD3DSurface *iface, IWineD3DClipper **clipper) +{ + IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface; + TRACE("(%p)->(%p)\n", This, clipper); + + *clipper = This->clipper; + IWineD3DClipper_AddRef(*clipper); + return WINED3D_OK; +} + const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl = { /* IUnknown */ @@ -3459,6 +3525,8 @@ const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl = IWineD3DSurfaceImpl_GetOverlayPosition, IWineD3DSurfaceImpl_UpdateOverlayZOrder, IWineD3DSurfaceImpl_UpdateOverlay, + IWineD3DSurfaceImpl_SetClipper, + IWineD3DSurfaceImpl_GetClipper, /* Internal use: */ IWineD3DSurfaceImpl_AddDirtyRect, IWineD3DSurfaceImpl_LoadTexture, diff --git a/dlls/wined3d/surface_gdi.c b/dlls/wined3d/surface_gdi.c index ce376800f69..7d277d46033 100644 --- a/dlls/wined3d/surface_gdi.c +++ b/dlls/wined3d/surface_gdi.c @@ -68,6 +68,13 @@ x11_copy_to_screen(IWineD3DSurfaceImpl *This, TRACE(" copying rect (%d,%d)->(%d,%d), offset (%d,%d)\n", rc->left, rc->top, rc->right, rc->bottom, offset.x, offset.y); } + + /* Front buffer coordinates are screen coordinates. Map them to the destination + * window if not fullscreened + */ + if(!This->resource.wineD3DDevice->ddraw_fullscreen) { + ClientToScreen(hDisplayWnd, &offset); + } #if 0 /* FIXME: this doesn't work... if users really want to run * X in 8bpp, then we need to call directly into display.drv @@ -88,7 +95,7 @@ x11_copy_to_screen(IWineD3DSurfaceImpl *This, if (This->clipper) { RECT xrc; - HWND hwnd = This->clipper->hWnd; + HWND hwnd = ((IWineD3DClipperImpl *) This->clipper)->hWnd; if (hwnd && GetClientRect(hwnd,&xrc)) { OffsetRect(&xrc,offset.x,offset.y); @@ -555,8 +562,7 @@ IWineGDISurfaceImpl_Blt(IWineD3DSurface *iface, ret = WINED3DERR_WRONGTEXTUREFORMAT; goto release; } - TRACE("Fourcc->Fourcc copy)\n"); - memcpy(dlock.pBits, slock.pBits, This->currentDesc.Height * dlock.Pitch); + memcpy(dlock.pBits, slock.pBits, This->resource.size); goto release; } @@ -1590,6 +1596,8 @@ const IWineD3DSurfaceVtbl IWineGDISurface_Vtbl = IWineD3DSurfaceImpl_GetOverlayPosition, IWineD3DSurfaceImpl_UpdateOverlayZOrder, IWineD3DSurfaceImpl_UpdateOverlay, + IWineD3DSurfaceImpl_SetClipper, + IWineD3DSurfaceImpl_GetClipper, /* Internal use: */ IWineD3DSurfaceImpl_AddDirtyRect, IWineGDISurfaceImpl_LoadTexture, diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 2883cde4d15..fc36584fba1 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -1 +1,2 @@ @ stdcall WineDirect3DCreate(long long ptr) +@ stdcall WineDirect3DCreateClipper(ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index f7c030306f3..d38c36b853f 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1013,6 +1013,19 @@ typedef struct { } renderbuffer_entry_t; /***************************************************************************** + * IWineD3DClipp implementation structure + */ +typedef struct IWineD3DClipperImpl +{ + const IWineD3DClipperVtbl *lpVtbl; + LONG ref; + + IUnknown *Parent; + HWND hWnd; +} IWineD3DClipperImpl; + + +/***************************************************************************** * IWineD3DSurface implementation structure */ struct IWineD3DSurfaceImpl @@ -1066,6 +1079,9 @@ struct IWineD3DSurfaceImpl struct list renderbuffers; renderbuffer_entry_t *current_renderbuffer; + + /* DirectDraw clippers */ + IWineD3DClipper *clipper; }; extern const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl; @@ -1113,6 +1129,8 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LO HRESULT WINAPI IWineD3DSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y); HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref); HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *SrcRect, IWineD3DSurface *DstSurface, RECT *DstRect, DWORD Flags, WINEDDOVERLAYFX *FX); +HRESULT WINAPI IWineD3DSurfaceImpl_SetClipper(IWineD3DSurface *iface, IWineD3DClipper *clipper); +HRESULT WINAPI IWineD3DSurfaceImpl_GetClipper(IWineD3DSurface *iface, IWineD3DClipper **clipper); /* Surface flags: */ #define SFLAG_OVERSIZE 0x00000001 /* Surface is bigger than gl size, blts only */ diff --git a/dlls/winmm/time.c b/dlls/winmm/time.c index 891b5695536..27a4e46bd39 100644 --- a/dlls/winmm/time.c +++ b/dlls/winmm/time.c @@ -44,8 +44,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(mmtime); static HANDLE TIME_hMMTimer; static LPWINE_TIMERENTRY TIME_TimersList; -static HANDLE TIME_hKillEvent; static HANDLE TIME_hWakeEvent; +static CRITICAL_SECTION TIME_cbcrst; static BOOL TIME_TimeToDie = TRUE; /* @@ -200,11 +200,11 @@ static LPWINE_TIMERENTRY lpTimers; ptimer = next_ptimer; } - if (TIME_hKillEvent) ResetEvent(TIME_hKillEvent); LeaveCriticalSection(&iData->cs); + EnterCriticalSection(&TIME_cbcrst); while (idx > 0) TIME_TriggerCallBack(&lpTimers[--idx]); - if (TIME_hKillEvent) SetEvent(TIME_hKillEvent); + LeaveCriticalSection(&TIME_cbcrst); /* Finally, adjust the recommended wait time downward by the amount of time the processing routines @@ -266,6 +266,8 @@ void TIME_MMTimeStart(void) TIME_TimeToDie = FALSE; TIME_hMMTimer = CreateThread(NULL, 0, TIME_MMSysTimeThread, &WINMM_IData, 0, NULL); SetThreadPriority(TIME_hMMTimer, THREAD_PRIORITY_TIME_CRITICAL); + InitializeCriticalSection(&TIME_cbcrst); + TIME_cbcrst.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINMM.TIME_cbcrst"); } } @@ -285,6 +287,8 @@ void TIME_MMTimeStop(void) CloseHandle(TIME_hMMTimer); CloseHandle(TIME_hWakeEvent); TIME_hMMTimer = 0; + TIME_cbcrst.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&TIME_cbcrst); TIME_TimersList = NULL; } } @@ -337,9 +341,6 @@ WORD TIME_SetEventInternal(UINT wDelay, UINT wResol, EnterCriticalSection(&WINMM_IData.cs); - if ((wFlags & TIME_KILL_SYNCHRONOUS) && !TIME_hKillEvent) - TIME_hKillEvent = CreateEventW(NULL, TRUE, TRUE, NULL); - for (lpTimer = TIME_TimersList; lpTimer != NULL; lpTimer = lpTimer->lpNext) { wNewID = max(wNewID, lpTimer->wTimerID); } @@ -397,8 +398,10 @@ MMRESULT WINAPI timeKillEvent(UINT wID) return MMSYSERR_INVALPARAM; } if (lpSelf->wFlags & TIME_KILL_SYNCHRONOUS) - WaitForSingleObject(TIME_hKillEvent, INFINITE); + EnterCriticalSection(&TIME_cbcrst); HeapFree(GetProcessHeap(), 0, lpSelf); + if (lpSelf->wFlags & TIME_KILL_SYNCHRONOUS) + LeaveCriticalSection(&TIME_cbcrst); return TIMERR_NOERROR; } diff --git a/include/winbase.h b/include/winbase.h index c45fbf119f3..7d6a827927f 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -664,6 +664,7 @@ typedef struct _TIME_ZONE_INFORMATION{ #define FILE_FLAG_DELETE_ON_CLOSE 0x04000000L #define FILE_FLAG_BACKUP_SEMANTICS 0x02000000L #define FILE_FLAG_POSIX_SEMANTICS 0x01000000L +#define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000L #define CREATE_NEW 1 #define CREATE_ALWAYS 2 #define OPEN_EXISTING 3 diff --git a/include/wincrypt.h b/include/wincrypt.h index 2219bd5b4f1..c580d845388 100644 --- a/include/wincrypt.h +++ b/include/wincrypt.h @@ -1613,6 +1613,11 @@ static const WCHAR MS_SCARD_PROV_W[] = { 'M','i','c','r','o','s','o',' #define PP_KEYSPEC 39 #define PP_ENUMEX_SIGNING_PROT 40 +/* Values returned by CryptGetProvParam of PP_KEYSTORAGE */ +#define CRYPT_SEC_DESCR 0x00000001 +#define CRYPT_PSTORE 0x00000002 +#define CRYPT_UI_PROMPT 0x00000004 + /* Crypt{Get/Set}KeyParam */ #define KP_IV 1 #define KP_SALT 2 diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h index 82ddc234596..c1bbd6b3c40 100644 --- a/include/wine/wined3d_interface.h +++ b/include/wine/wined3d_interface.h @@ -79,6 +79,7 @@ struct IWineD3DSurface; #define WINEDDERR_NOTFLIPPABLE MAKE_WINED3DHRESULT(582) #define WINEDDERR_SURFACEBUSY MAKE_WINED3DHRESULT(430) #define WINEDDERR_INVALIDRECT MAKE_WINED3DHRESULT(150) +#define WINEDDERR_NOCLIPLIST MAKE_WINED3DHRESULT(205) #define WINED3DOK_NOAUTOGEN MAKE_WINED3DSTATUS(2159) /***************************************************************************** @@ -104,6 +105,7 @@ struct IWineD3DVertexShader; struct IWineD3DPixelShader; struct IWineD3DQuery; struct IWineD3DSwapChain; +struct IWineD3DClipper; /* {108F9C44-6F30-11d9-C687-00046142C14F} */ @@ -187,6 +189,10 @@ DEFINE_GUID(IID_IWineD3DStateBlock, DEFINE_GUID(IID_IWineD3DQuery, 0x905ddbac, 0x6f30, 0x11d9, 0xc6, 0x87, 0x0, 0x4, 0x61, 0x42, 0xc1, 0x4f); +/* {8f2bceb1-d338-488c-ab7f-0ec980bf5d2d} */ +DEFINE_GUID(IID_IWineD3DClipper, +0x8f2bceb1, 0xd338, 0x488c, 0xab, 0x7f, 0x0e, 0xc9, 0x80, 0xbf, 0x5d, 0x2d); + /***************************************************************************** * Callback functions required for predefining surfaces / stencils */ @@ -1119,6 +1125,8 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWineD3DResource) STDMETHOD(GetOverlayPosition)(THIS_ LONG *X, LONG *Y) PURE; STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD Flags, IWineD3DSurface *Ref) PURE; STDMETHOD(UpdateOverlay)(THIS_ RECT *SrcRect, IWineD3DSurface *DstSurface, RECT *DstRect, DWORD Flags, WINEDDOVERLAYFX *FX); + STDMETHOD(SetClipper)(THIS_ struct IWineD3DClipper *clipper); + STDMETHOD(GetClipper)(THIS_ struct IWineD3DClipper **clipper); /* Internally used methods */ STDMETHOD(AddDirtyRect)(THIS_ CONST RECT* pRect) PURE; STDMETHOD(LoadTexture)(THIS) PURE; @@ -1172,6 +1180,8 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWineD3DResource) #define IWineD3DSurface_GetOverlayPosition(p, a, b) (p)->lpVtbl->GetOverlayPosition(p, a, b) #define IWineD3DSurface_UpdateOverlayZOrder(p, a, b) (p)->lpVtbl->UpdateOverlayZOrder(p, a, b) #define IWineD3DSurface_UpdateOverlay(p, a, b, c, d, e) (p)->lpVtbl->UpdateOverlay(p, a, b, c, d, e) +#define IWineD3DSurface_SetClipper(p, a) (p)->lpVtbl->SetClipper(p, a) +#define IWineD3DSurface_GetClipper(p, a) (p)->lpVtbl->GetClipper(p, a) /*** IWineD3DSurface (Internal, no d3d mapping) methods ***/ #define IWineD3DSurface_AddDirtyRect(p,a) (p)->lpVtbl->AddDirtyRect(p,a) #define IWineD3DSurface_LoadTexture(p) (p)->lpVtbl->LoadTexture(p) @@ -1532,6 +1542,54 @@ DECLARE_INTERFACE_(IWineD3DPalette,IUnknown) #define IWineD3DPalette_SetEntries(p, a, b, c, d) (p)->lpVtbl->SetEntries(p, a, b, c, d) #endif +/***************************************************************************** + * IDirectDrawClipper interface + */ +#define INTERFACE IWineD3DClipper +DECLARE_INTERFACE_(IWineD3DClipper,IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + /*** WineD3DBase methods ***/ + STDMETHOD_(HRESULT,GetParent)(THIS_ IUnknown **parent) PURE; + /*** IWineD3DClipper methods ***/ + STDMETHOD(GetClipList)(THIS_ LPRECT lpRect, LPRGNDATA lpClipList, LPDWORD lpdwSize) PURE; + STDMETHOD(GetHWnd)(THIS_ HWND *lphWnd) PURE; + STDMETHOD(IsClipListChanged)(THIS_ BOOL *lpbChanged) PURE; + STDMETHOD(SetClipList)(THIS_ LPRGNDATA lpClipList, DWORD dwFlags) PURE; + STDMETHOD(SetHWnd)(THIS_ DWORD dwFlags, HWND hWnd) PURE; +}; +#undef INTERFACE + +#if !defined(__cplusplus) || defined(CINTERFACE) +/*** IUnknown methods ***/ +#define IWineD3DClipper_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IWineD3DClipper_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IWineD3DClipper_Release(p) (p)->lpVtbl->Release(p) +/*** IWineD3DClipper methods ***/ +#define IWineD3DClipper_GetClipList(p,a,b,c) (p)->lpVtbl->GetClipList(p,a,b,c) +#define IWineD3DClipper_GetHWnd(p,a) (p)->lpVtbl->GetHWnd(p,a) +#define IWineD3DClipper_IsClipListChanged(p,a) (p)->lpVtbl->IsClipListChanged(p,a) +#define IWineD3DClipper_SetClipList(p,a,b) (p)->lpVtbl->SetClipList(p,a,b) +#define IWineD3DClipper_SetHWnd(p,a,b) (p)->lpVtbl->SetHWnd(p,a,b) +#else +/*** IUnknown methods ***/ +#define IWineD3DClipper_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IWineD3DClipper_AddRef(p) (p)->AddRef() +#define IWineD3DClipper_Release(p) (p)->Release() +/*** IWineD3DClipper methods ***/ +#define IWineD3DClipper_GetClipList(p,a,b,c) (p)->GetClipList(a,b,c) +#define IWineD3DClipper_GetHWnd(p,a) (p)->GetHWnd(a) +#define IWineD3DClipper_IsClipListChanged(p,a) (p)->IsClipListChanged(a) +#define IWineD3DClipper_SetClipList(p,a,b) (p)->SetClipList(a,b) +#define IWineD3DClipper_SetHWnd(p,a,b) (p)->SetHWnd(a,b) +#endif + +/* DDraw Clippers are not created from DDraw objects, they have a seperate creation function */ +IWineD3DClipper* WINAPI WineDirect3DCreateClipper(IUnknown *parent); + #if 0 /* FIXME: During porting in from d3d8 - the following will be used */ extern HRESULT WINAPI IDirect3DVertexShaderImpl_ParseProgram(IDirect3DVertexShaderImpl* This, CONST DWORD* pFunction); /* internal Interfaces */ diff --git a/include/winsvc.h b/include/winsvc.h index 617b9f4bac7..8f6184dcad7 100644 --- a/include/winsvc.h +++ b/include/winsvc.h @@ -185,13 +185,28 @@ typedef struct _ENUM_SERVICE_STATUSW { SERVICE_STATUS ServiceStatus; } ENUM_SERVICE_STATUSW, *LPENUM_SERVICE_STATUSW; +DECL_WINELIB_TYPE_AW(ENUM_SERVICE_STATUS) +DECL_WINELIB_TYPE_AW(LPENUM_SERVICE_STATUS) + +typedef struct _ENUM_SERVICE_STATUS_PROCESSA { + LPSTR lpServiceName; + LPSTR lpDisplayName; + SERVICE_STATUS_PROCESS ServiceStatusProcess; +} ENUM_SERVICE_STATUS_PROCESSA, *LPENUM_SERVICE_STATUS_PROCESSA; + +typedef struct _ENUM_SERVICE_STATUS_PROCESSW { + LPWSTR lpServiceName; + LPWSTR lpDisplayName; + SERVICE_STATUS_PROCESS ServiceStatusProcess; +} ENUM_SERVICE_STATUS_PROCESSW, *LPENUM_SERVICE_STATUS_PROCESSW; + +DECL_WINELIB_TYPE_AW(ENUM_SERVICE_STATUS_PROCESS) +DECL_WINELIB_TYPE_AW(LPENUM_SERVICE_STATUS_PROCESS) + typedef enum _SC_ENUM_TYPE { SC_ENUM_PROCESS_INFO = 0 } SC_ENUM_TYPE; -DECL_WINELIB_TYPE_AW(ENUM_SERVICE_STATUS) -DECL_WINELIB_TYPE_AW(LPENUM_SERVICE_STATUS) - typedef struct _QUERY_SERVICE_CONFIGA { DWORD dwServiceType; DWORD dwStartType; @@ -307,6 +322,11 @@ BOOL WINAPI EnumServicesStatusA(SC_HANDLE,DWORD,DWORD,LPENUM_SERVICE_STAT BOOL WINAPI EnumServicesStatusW(SC_HANDLE,DWORD,DWORD,LPENUM_SERVICE_STATUSW, DWORD,LPDWORD,LPDWORD,LPDWORD); #define EnumServicesStatus WINELIB_NAME_AW(EnumServicesStatus) +BOOL WINAPI EnumServicesStatusExA(SC_HANDLE,SC_ENUM_TYPE,DWORD,DWORD,LPBYTE, + DWORD,LPDWORD,LPDWORD,LPDWORD,LPCSTR); +BOOL WINAPI EnumServicesStatusExW(SC_HANDLE,SC_ENUM_TYPE,DWORD,DWORD,LPBYTE, + DWORD,LPDWORD,LPDWORD,LPDWORD,LPCWSTR); +#define EnumServicesStatus WINELIB_NAME_AW(EnumServicesStatus) BOOL WINAPI GetServiceDisplayNameA(SC_HANDLE,LPCSTR,LPSTR,LPDWORD); BOOL WINAPI GetServiceDisplayNameW(SC_HANDLE,LPCWSTR,LPWSTR,LPDWORD); #define GetServiceDisplayName WINELIB_NAME_AW(GetServiceDisplayName) diff --git a/tools/wine.inf b/tools/wine.inf index 9b061ef4e8e..ee6a287540f 100644 --- a/tools/wine.inf +++ b/tools/wine.inf @@ -2153,6 +2153,7 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G" 11,,wintrust.dll,1 [FakeDllsSection] +10,,explorer.exe 10,,notepad.exe 10,,regedit.exe 10,,winebrowser.exe @@ -2173,7 +2174,6 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G" 11,,ddraw.dll 11,,dsound.dll 11,,dsound.vxd -11,,explorer.exe 11,,gdi32.dll 11,,hhctrl.ocx 11,,imaadp32.acm diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index f1a7bb0acde..3955276486d 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -724,7 +724,9 @@ static int is_linker_arg(const char* arg) switch (arg[1]) { - case 'l': + case 'R': + case 'z': + case 'l': case 'u': return 1; case 'W': @@ -828,7 +830,7 @@ int main(int argc, char **argv) case 'x': case 'o': case 'D': case 'U': case 'I': case 'A': case 'l': case 'u': case 'b': case 'V': case 'G': case 'L': - case 'B': + case 'B': case 'R': case 'z': if (argv[i][2]) option_arg = &argv[i][2]; else next_is_arg = 1; break; -- 2.11.4.GIT