From 558fe11c1f16005c73b045030821f97897898733 Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Thu, 27 Sep 2007 06:02:40 +0200 Subject: [PATCH] push 9e21362176c984932a6a2e40fa620c4fb646f307 --- configure | 89 +++ configure.ac | 9 + dlls/advapi32/advapi32.spec | 6 +- dlls/advapi32/crypt.c | 2 +- dlls/advapi32/crypt_lmhash.c | 4 +- dlls/advapi32/security.c | 512 +++++++++++++++-- dlls/advapi32/service.c | 2 +- dlls/advapi32/tests/security.c | 112 +++- dlls/advapi32/tests/service.c | 2 +- dlls/comcat/regsvr.c | 63 +- dlls/comdlg32/tests/printdlg.c | 78 ++- dlls/crypt32/Makefile.in | 2 + dlls/crypt32/main.c | 13 - dlls/crypt32/object.c | 471 +++++++++++++++ dlls/d3dxof/regsvr.c | 79 +-- dlls/ddraw/regsvr.c | 76 +-- dlls/ddrawex/regsvr.c | 73 +-- dlls/dinput/device.c | 51 ++ dlls/dinput/device_private.h | 3 + dlls/dinput/joystick_linux.c | 37 +- dlls/dinput/joystick_linuxinput.c | 143 +++-- dlls/dinput/regsvr.c | 79 +-- dlls/dinput8/regsvr.c | 73 +-- dlls/dplayx/dplay.c | 7 + dlls/dplayx/name_server.c | 1 + dlls/gdi32/clipping.c | 20 +- dlls/gdi32/driver.c | 20 +- dlls/gdi32/mapping.c | 52 +- dlls/gdi32/opengl.c | 26 +- dlls/gdi32/painting.c | 14 +- dlls/gdi32/path.c | 48 +- dlls/gdi32/printdrv.c | 50 +- dlls/itss/protocol.c | 2 +- dlls/kernel32/tests/virtual.c | 36 ++ dlls/mpr/pwcache.c | 5 +- dlls/mshtml/htmlbody.c | 10 +- dlls/mshtml/htmlelem.c | 2 +- dlls/mshtml/view.c | 3 +- dlls/msvcrt/dir.c | 63 ++ dlls/msvcrt/file.c | 14 +- dlls/msvcrt/math.c | 77 ++- dlls/msvcrt/msvcrt.h | 4 +- dlls/msvcrt/msvcrt.spec | 10 +- dlls/msvcrt/process.c | 183 +++++- dlls/msvcrt/tests/printf.c | 107 +++- dlls/ntdll/loader.c | 2 +- dlls/ntdll/ntdll.spec | 4 +- dlls/ntdll/sec.c | 21 +- dlls/ntdll/sync.c | 125 +++- dlls/ole32/oleproxy.c | 3 +- dlls/ole32/tests/storage32.c | 3 - dlls/opengl32/make_opengl | 2 + dlls/opengl32/opengl_norm.c | 20 - dlls/opengl32/wgl.c | 22 + dlls/riched20/editor.c | 15 +- dlls/riched20/tests/editor.c | 106 +++- dlls/setupapi/devinst.c | 1120 +++++++++++++++++++++++++++++++++--- dlls/setupapi/setupapi.spec | 5 + dlls/setupapi/stubs.c | 29 - dlls/setupapi/tests/devinst.c | 168 ++++++ dlls/shdocvw/shdocvw.h | 1 + dlls/shdocvw/tests/webbrowser.c | 40 ++ dlls/shdocvw/webbrowser.c | 27 +- dlls/shell32/shell32.spec | 4 +- dlls/shell32/shellord.c | 10 +- dlls/shell32/shlview.c | 99 ++-- dlls/user32/input.c | 92 +++ dlls/user32/tests/msg.c | 229 +++++--- dlls/user32/user32.spec | 16 +- dlls/wined3d/arb_program_shader.c | 463 +++++++++++++-- dlls/wined3d/baseshader.c | 4 + dlls/wined3d/device.c | 30 +- dlls/wined3d/directx.c | 31 +- dlls/wined3d/glsl_shader.c | 233 +++++++- dlls/wined3d/pixelshader.c | 139 ++++- dlls/wined3d/resource.c | 2 +- dlls/wined3d/state.c | 8 +- dlls/wined3d/surface.c | 55 +- dlls/wined3d/utils.c | 57 +- dlls/wined3d/wined3d_main.c | 22 - dlls/wined3d/wined3d_private.h | 50 +- dlls/wineps.drv/init.c | 2 +- dlls/winex11.drv/opengl.c | 22 +- dlls/winex11.drv/x11drv_main.c | 71 +++ dlls/winex11.drv/xcomposite.h | 45 ++ dlls/wininet/internet.c | 14 +- dlls/ws2_32/socket.c | 14 + dlls/ws2_32/tests/sock.c | 48 ++ dlls/wtsapi32/wtsapi32.c | 18 + dlls/wtsapi32/wtsapi32.spec | 2 + include/config.h.in | 6 + include/iads.idl | 24 + include/setupapi.h | 4 +- include/shlobj.h | 2 +- include/winbase.h | 1 + include/wine/server_protocol.h | 95 ++- include/wine/wined3d_gl.h | 2 + include/winnt.h | 2 +- include/winternl.h | 1 + include/winuser.h | 69 ++- programs/winecfg/audio.c | 3 +- programs/winecfg/idw_testsound.wav | Bin 0 -> 12348 bytes programs/winecfg/resource.h | 1 + programs/winecfg/winecfg.rc | 3 + programs/wineconsole/curses.c | 2 + programs/wineconsole/user.c | 2 +- programs/wineconsole/wineconsole.c | 24 +- server/Makefile.in | 1 + server/completion.c | 242 ++++++++ server/protocol.def | 52 ++ server/request.h | 10 + server/trace.c | 76 +++ tools/widl/typegen.c | 15 +- tools/wine.inf | 22 + 114 files changed, 5639 insertions(+), 1246 deletions(-) create mode 100644 dlls/crypt32/object.c create mode 100644 dlls/winex11.drv/xcomposite.h create mode 100644 programs/winecfg/idw_testsound.wav create mode 100644 server/completion.c diff --git a/configure b/configure index 421a2fa7fa3..cbeafe0c490 100755 --- a/configure +++ b/configure @@ -9260,6 +9260,7 @@ fi + for ac_header in X11/Xlib.h \ X11/XKBlib.h \ X11/Xutil.h \ @@ -9267,6 +9268,7 @@ for ac_header in X11/Xlib.h \ X11/extensions/shape.h \ X11/extensions/XInput.h \ X11/extensions/XShm.h \ + X11/extensions/Xcomposite.h \ X11/extensions/Xinerama.h \ X11/extensions/Xrandr.h \ X11/extensions/Xrender.h \ @@ -10218,6 +10220,93 @@ Wine will be built without Xinerama support. (winex11.drv)" fi + if test "$ac_cv_header_X11_extensions_Xcomposite_h" = "yes" + then + { echo "$as_me:$LINENO: checking for -lXcomposite" >&5 +echo $ECHO_N "checking for -lXcomposite... $ECHO_C" >&6; } +if test "${ac_cv_lib_soname_Xcomposite+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_soname_save_LIBS=$LIBS +LIBS="-lXcomposite $X_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XCompositeRedirectWindow (); +int +main () +{ +return XCompositeRedirectWindow (); + ; + 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 + case "$LIBEXT" in + dll) ;; + dylib) ac_cv_lib_soname_Xcomposite=`otool -L conftest$ac_exeext | grep "libXcomposite\\.[0-9A-Za-z.]*dylib" | sed -e "s/^.*\/\(libXcomposite\.[0-9A-Za-z.]*dylib\).*$/\1/"';2,$d'` ;; + *) ac_cv_lib_soname_Xcomposite=`$ac_cv_path_LDD conftest$ac_exeext | grep "libXcomposite\\.$LIBEXT" | sed -e "s/^.*\(libXcomposite\.$LIBEXT[^ ]*\).*$/\1/"';2,$d'` ;; + esac +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + LIBS=$ac_check_soname_save_LIBS +fi +if test "x$ac_cv_lib_soname_Xcomposite" = "x"; then + { echo "$as_me:$LINENO: result: not found" >&5 +echo "${ECHO_T}not found" >&6; } + +else + { echo "$as_me:$LINENO: result: $ac_cv_lib_soname_Xcomposite" >&5 +echo "${ECHO_T}$ac_cv_lib_soname_Xcomposite" >&6; } + +cat >>confdefs.h <<_ACEOF +#define SONAME_LIBXCOMPOSITE "$ac_cv_lib_soname_Xcomposite" +_ACEOF + + +fi + + fi + if test "x$ac_cv_lib_soname_Xcomposite" = "x"; then + wine_notices="$wine_notices|XComposite development files not found. +Wine will be built without XComposite support. (winex11.drv)" +fi + + if test "x$with_opengl" != "xno" then diff --git a/configure.ac b/configure.ac index 86a8effb044..cdf5d7bd03c 100644 --- a/configure.ac +++ b/configure.ac @@ -529,6 +529,7 @@ then X11/extensions/shape.h \ X11/extensions/XInput.h \ X11/extensions/XShm.h \ + X11/extensions/Xcomposite.h \ X11/extensions/Xinerama.h \ X11/extensions/Xrandr.h \ X11/extensions/Xrender.h \ @@ -625,6 +626,14 @@ Wine will be built without XRandr support. (winex11.drv)]) WINE_NOTICE_IF([test "x$ac_cv_lib_soname_Xinerama" = "x"],[Xinerama development files not found. Wine will be built without Xinerama support. (winex11.drv)]) + dnl *** Check for X Composite extension + if test "$ac_cv_header_X11_extensions_Xcomposite_h" = "yes" + then + WINE_CHECK_SONAME(Xcomposite,XCompositeRedirectWindow,,,[$X_LIBS -lXext -lX11 $X_EXTRA_LIBS]) + fi + WINE_NOTICE_IF([test "x$ac_cv_lib_soname_Xcomposite" = "x"],[XComposite development files not found. +Wine will be built without XComposite support. (winex11.drv)]) + dnl *** End of X11/Xlib.h check dnl Check for the presence of OpenGL diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index 20f333d53e7..6cb88467f93 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -22,7 +22,7 @@ # @ stub AddAccessDeniedObjectAce @ stdcall AddAce(ptr long long ptr long) @ stdcall AddAuditAccessAce(ptr long long ptr long long) -# @ stub AddAuditAccessAceEx +@ stdcall AddAuditAccessAceEx(ptr long long long ptr long long) # @ stub AddAuditAccessObjectAce # @ stub AddUsersToEncryptedFile @ stdcall AdjustTokenGroups(long long ptr long ptr ptr) @@ -75,8 +75,8 @@ # @ stub ConvertSecurityDescriptorToAccessNamedA # @ stub ConvertSecurityDescriptorToAccessNamedW # @ stub ConvertSecurityDescriptorToAccessW -# @ stub ConvertSecurityDescriptorToStringSecurityDescriptorA -# @ stub ConvertSecurityDescriptorToStringSecurityDescriptorW +@ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorA(ptr long long ptr ptr) +@ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorW(ptr long long ptr ptr) @ stdcall ConvertSidToStringSidA(ptr ptr) @ stdcall ConvertSidToStringSidW(ptr ptr) # @ stub ConvertStringSDToSDDomainA diff --git a/dlls/advapi32/crypt.c b/dlls/advapi32/crypt.c index 63f89f6869a..c6ea9405de5 100644 --- a/dlls/advapi32/crypt.c +++ b/dlls/advapi32/crypt.c @@ -146,7 +146,7 @@ static inline BOOL CRYPT_UnicodeToANSI(LPCWSTR wstr, LPSTR* str, int strsize) */ static inline BOOL CRYPT_ANSIToUnicode(LPCSTR str, LPWSTR* wstr, int wstrsize) { - int wcount; + unsigned int wcount; if (!str) { diff --git a/dlls/advapi32/crypt_lmhash.c b/dlls/advapi32/crypt_lmhash.c index 2f5784266af..345c89ddb73 100644 --- a/dlls/advapi32/crypt_lmhash.c +++ b/dlls/advapi32/crypt_lmhash.c @@ -194,7 +194,7 @@ NTSTATUS WINAPI SystemFunction004(const struct ustring *in, unsigned int ui[2]; } data; unsigned char deskey[7]; - int crypt_len, ofs; + unsigned int crypt_len, ofs; if (key->Length<=0) return STATUS_INVALID_PARAMETER_2; @@ -253,7 +253,7 @@ NTSTATUS WINAPI SystemFunction005(const struct ustring *in, unsigned int ui[2]; } data; unsigned char deskey[7]; - int ofs, crypt_len; + unsigned int ofs, crypt_len; if (key->Length<=0) return STATUS_INVALID_PARAMETER_2; diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index 4c41e0cad1f..9323c07f00a 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -35,6 +35,8 @@ #include "sddl.h" #include "winsvc.h" #include "aclapi.h" +#include "objbase.h" +#include "iads.h" #include "advapi32_misc.h" #include "wine/debug.h" @@ -246,12 +248,40 @@ static const WCHAR SDDL_READ_CONTROL[] = {'R','C',0}; static const WCHAR SDDL_WRITE_DAC[] = {'W','D',0}; static const WCHAR SDDL_WRITE_OWNER[] = {'W','O',0}; static const WCHAR SDDL_STANDARD_DELETE[] = {'S','D',0}; + +static const WCHAR SDDL_READ_PROPERTY[] = {'R','P',0}; +static const WCHAR SDDL_WRITE_PROPERTY[] = {'W','P',0}; +static const WCHAR SDDL_CREATE_CHILD[] = {'C','C',0}; +static const WCHAR SDDL_DELETE_CHILD[] = {'D','C',0}; +static const WCHAR SDDL_LIST_CHILDREN[] = {'L','C',0}; +static const WCHAR SDDL_SELF_WRITE[] = {'S','W',0}; +static const WCHAR SDDL_LIST_OBJECT[] = {'L','O',0}; +static const WCHAR SDDL_DELETE_TREE[] = {'D','T',0}; +static const WCHAR SDDL_CONTROL_ACCESS[] = {'C','R',0}; + +static const WCHAR SDDL_FILE_ALL[] = {'F','A',0}; +static const WCHAR SDDL_FILE_READ[] = {'F','R',0}; +static const WCHAR SDDL_FILE_WRITE[] = {'F','W',0}; +static const WCHAR SDDL_FILE_EXECUTE[] = {'F','X',0}; + +static const WCHAR SDDL_KEY_ALL[] = {'K','A',0}; +static const WCHAR SDDL_KEY_READ[] = {'K','R',0}; +static const WCHAR SDDL_KEY_WRITE[] = {'K','W',0}; +static const WCHAR SDDL_KEY_EXECUTE[] = {'K','X',0}; + static const WCHAR SDDL_GENERIC_ALL[] = {'G','A',0}; static const WCHAR SDDL_GENERIC_READ[] = {'G','R',0}; static const WCHAR SDDL_GENERIC_WRITE[] = {'G','W',0}; static const WCHAR SDDL_GENERIC_EXECUTE[] = {'G','X',0}; /* + * ACL flags + */ +static const WCHAR SDDL_PROTECTED[] = {'P',0}; +static const WCHAR SDDL_AUTO_INHERIT_REQ[] = {'A','R',0}; +static const WCHAR SDDL_AUTO_INHERITED[] = {'A','I',0}; + +/* * ACE types */ static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0}; @@ -749,7 +779,7 @@ CreateWellKnownSid( WELL_KNOWN_SID_TYPE WellKnownSidType, PSID pSid, DWORD* cbSid) { - int i; + unsigned int i; TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid); if (DomainSid != NULL) { @@ -788,7 +818,7 @@ CreateWellKnownSid( WELL_KNOWN_SID_TYPE WellKnownSidType, BOOL WINAPI IsWellKnownSid( PSID pSid, WELL_KNOWN_SID_TYPE WellKnownSidType ) { - int i; + unsigned int i; TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType); for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) @@ -1604,7 +1634,7 @@ LookupPrivilegeNameA( LPCSTR lpSystemName, PLUID lpLuid, LPSTR lpName, if (ret) { /* Windows crashes if cchName is NULL, so will I */ - int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName, + unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName, *cchName, NULL, NULL); if (len == 0) @@ -1847,7 +1877,7 @@ LookupAccountSidW( IN OUT LPDWORD domainSize, OUT PSID_NAME_USE name_use ) { - int i, j; + unsigned int i, j; const WCHAR * ac = NULL; const WCHAR * dm = NULL; SID_NAME_USE use = 0; @@ -2260,6 +2290,22 @@ BOOL WINAPI AddAuditAccessAce( } /****************************************************************************** + * AddAuditAccessAce [ADVAPI32.@] + */ +BOOL WINAPI AddAuditAccessAceEx( + IN OUT PACL pAcl, + IN DWORD dwAceRevision, + IN DWORD dwAceFlags, + IN DWORD dwAccessMask, + IN PSID pSid, + IN BOOL bAuditSuccess, + IN BOOL bAuditFailure) +{ + return set_ntstatus( RtlAddAuditAccessAceEx(pAcl, dwAceRevision, dwAceFlags, dwAccessMask, pSid, + bAuditSuccess, bAuditFailure) ); +} + +/****************************************************************************** * LookupAccountNameA [ADVAPI32.@] */ BOOL WINAPI @@ -3107,10 +3153,31 @@ static const ACEFLAG AceRights[] = { SDDL_GENERIC_READ, GENERIC_READ }, { SDDL_GENERIC_WRITE, GENERIC_WRITE }, { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE }, + { SDDL_READ_CONTROL, READ_CONTROL }, { SDDL_STANDARD_DELETE, DELETE }, { SDDL_WRITE_DAC, WRITE_DAC }, { SDDL_WRITE_OWNER, WRITE_OWNER }, + + { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP}, + { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP}, + { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD}, + { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD}, + { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST}, + { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF}, + { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT}, + { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE}, + { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS}, + + { SDDL_FILE_ALL, FILE_ALL_ACCESS }, + { SDDL_FILE_READ, FILE_GENERIC_READ }, + { SDDL_FILE_WRITE, FILE_GENERIC_WRITE }, + { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE }, + + { SDDL_KEY_ALL, KEY_ALL_ACCESS }, + { SDDL_KEY_READ, KEY_READ }, + { SDDL_KEY_WRITE, KEY_WRITE }, + { SDDL_KEY_EXECUTE, KEY_EXECUTE }, { NULL, 0 }, }; @@ -3475,6 +3542,401 @@ lend: return bret; } +static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen) +{ + if (cch == -1) + cch = strlenW(string); + + if (plen) + *plen += cch; + + if (pwptr) + { + memcpy(*pwptr, string, sizeof(WCHAR)*cch); + *pwptr += cch; + } +} + +static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen) +{ + DWORD i; + WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 }; + WCHAR subauthfmt[] = { '-','%','u',0 }; + WCHAR buf[26]; + SID *pisid = psid; + + if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION) + { + SetLastError(ERROR_INVALID_SID); + return FALSE; + } + + if (pisid->IdentifierAuthority.Value[0] || + pisid->IdentifierAuthority.Value[1]) + { + FIXME("not matching MS' bugs\n"); + SetLastError(ERROR_INVALID_SID); + return FALSE; + } + + sprintfW( buf, fmt, pisid->Revision, + MAKELONG( + MAKEWORD( pisid->IdentifierAuthority.Value[5], + pisid->IdentifierAuthority.Value[4] ), + MAKEWORD( pisid->IdentifierAuthority.Value[3], + pisid->IdentifierAuthority.Value[2] ) + ) ); + DumpString(buf, -1, pwptr, plen); + + for( i=0; iSubAuthorityCount; i++ ) + { + sprintfW( buf, subauthfmt, pisid->SubAuthority[i] ); + DumpString(buf, -1, pwptr, plen); + } + return TRUE; +} + +static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen) +{ + int i; + for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++) + { + if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision))) + { + DumpString(WellKnownSids[i].wstr, 2, pwptr, plen); + return TRUE; + } + } + + return DumpSidNumeric(psid, pwptr, plen); +} + +const static LPCWSTR AceRightBitNames[32] = { + SDDL_CREATE_CHILD, /* 0 */ + SDDL_DELETE_CHILD, + SDDL_LIST_CHILDREN, + SDDL_SELF_WRITE, + SDDL_READ_PROPERTY, /* 4 */ + SDDL_WRITE_PROPERTY, + SDDL_DELETE_TREE, + SDDL_LIST_OBJECT, + SDDL_CONTROL_ACCESS, /* 8 */ + NULL, + NULL, + NULL, + NULL, /* 12 */ + NULL, + NULL, + NULL, + SDDL_STANDARD_DELETE, /* 16 */ + SDDL_READ_CONTROL, + SDDL_WRITE_DAC, + SDDL_WRITE_OWNER, + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, /* 24 */ + NULL, + NULL, + NULL, + SDDL_GENERIC_ALL, /* 28 */ + SDDL_GENERIC_EXECUTE, + SDDL_GENERIC_WRITE, + SDDL_GENERIC_READ +}; + +static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen) +{ + const static WCHAR fmtW[] = {'0','x','%','x',0}; + WCHAR buf[15]; + int i; + + if (mask == 0) + return; + + /* first check if the right have name */ + for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++) + { + if (AceRights[i].wstr == NULL) + break; + if (mask == AceRights[i].value) + { + DumpString(AceRights[i].wstr, -1, pwptr, plen); + return; + } + } + + /* then check if it can be built from bit names */ + for (i = 0; i < 32; i++) + { + if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL)) + { + /* can't be built from bit names */ + sprintfW(buf, fmtW, mask); + DumpString(buf, -1, pwptr, plen); + return; + } + } + + /* build from bit names */ + for (i = 0; i < 32; i++) + if (mask & (1 << i)) + DumpString(AceRightBitNames[i], -1, pwptr, plen); +} + +static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen) +{ + ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */ + const static WCHAR openbr = '('; + const static WCHAR closebr = ')'; + const static WCHAR semicolon = ';'; + + if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE)) + { + SetLastError(ERROR_INVALID_ACL); + return FALSE; + } + + piace = (ACCESS_ALLOWED_ACE *)pace; + DumpString(&openbr, 1, pwptr, plen); + switch (piace->Header.AceType) + { + case ACCESS_ALLOWED_ACE_TYPE: + DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen); + break; + case ACCESS_DENIED_ACE_TYPE: + DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen); + break; + case SYSTEM_AUDIT_ACE_TYPE: + DumpString(SDDL_AUDIT, -1, pwptr, plen); + break; + case SYSTEM_ALARM_ACE_TYPE: + DumpString(SDDL_ALARM, -1, pwptr, plen); + break; + } + DumpString(&semicolon, 1, pwptr, plen); + + if (piace->Header.AceFlags & OBJECT_INHERIT_ACE) + DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen); + if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE) + DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen); + if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) + DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen); + if (piace->Header.AceFlags & INHERIT_ONLY_ACE) + DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen); + if (piace->Header.AceFlags & INHERITED_ACE) + DumpString(SDDL_INHERITED, -1, pwptr, plen); + if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) + DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen); + if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) + DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen); + DumpString(&semicolon, 1, pwptr, plen); + DumpRights(piace->Mask, pwptr, plen); + DumpString(&semicolon, 1, pwptr, plen); + /* objects not supported */ + DumpString(&semicolon, 1, pwptr, plen); + /* objects not supported */ + DumpString(&semicolon, 1, pwptr, plen); + if (!DumpSid((PSID)&piace->SidStart, pwptr, plen)) + return FALSE; + DumpString(&closebr, 1, pwptr, plen); + return TRUE; +} + +static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited) +{ + WORD count; + int i; + + if (protected) + DumpString(SDDL_PROTECTED, -1, pwptr, plen); + if (autoInheritReq) + DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen); + if (autoInherited) + DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen); + + if (pacl == NULL) + return TRUE; + + if (!IsValidAcl(pacl)) + return FALSE; + + count = pacl->AceCount; + for (i = 0; i < count; i++) + { + LPVOID ace; + if (!GetAce(pacl, i, &ace)) + return FALSE; + if (!DumpAce(ace, pwptr, plen)) + return FALSE; + } + + return TRUE; +} + +static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen) +{ + const static WCHAR prefix[] = {'O',':',0}; + BOOL bDefaulted; + PSID psid; + + if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted)) + return FALSE; + + if (psid == NULL) + return TRUE; + + DumpString(prefix, -1, pwptr, plen); + if (!DumpSid(psid, pwptr, plen)) + return FALSE; + return TRUE; +} + +static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen) +{ + const static WCHAR prefix[] = {'G',':',0}; + BOOL bDefaulted; + PSID psid; + + if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted)) + return FALSE; + + if (psid == NULL) + return TRUE; + + DumpString(prefix, -1, pwptr, plen); + if (!DumpSid(psid, pwptr, plen)) + return FALSE; + return TRUE; +} + +static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen) +{ + static const WCHAR dacl[] = {'D',':',0}; + SECURITY_DESCRIPTOR_CONTROL control; + BOOL present, defaulted; + DWORD revision; + PACL pacl; + + if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted)) + return FALSE; + + if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision)) + return FALSE; + + if (!present) + return TRUE; + + DumpString(dacl, 2, pwptr, plen); + if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED)) + return FALSE; + return TRUE; +} + +static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen) +{ + static const WCHAR sacl[] = {'S',':',0}; + SECURITY_DESCRIPTOR_CONTROL control; + BOOL present, defaulted; + DWORD revision; + PACL pacl; + + if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted)) + return FALSE; + + if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision)) + return FALSE; + + if (!present) + return TRUE; + + DumpString(sacl, 2, pwptr, plen); + if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED)) + return FALSE; + return TRUE; +} + +/****************************************************************************** + * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@] + */ +BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, ULONG *OutputLen) +{ + ULONG len; + WCHAR *wptr, *wstr; + + if (SDRevision != SDDL_REVISION_1) + { + ERR("Pogram requested unknown SDDL revision %d\n", SDRevision); + SetLastError(ERROR_UNKNOWN_REVISION); + return FALSE; + } + + len = 0; + if (RequestedInformation & OWNER_SECURITY_INFORMATION) + if (!DumpOwner(SecurityDescriptor, NULL, &len)) + return FALSE; + if (RequestedInformation & GROUP_SECURITY_INFORMATION) + if (!DumpGroup(SecurityDescriptor, NULL, &len)) + return FALSE; + if (RequestedInformation & DACL_SECURITY_INFORMATION) + if (!DumpDacl(SecurityDescriptor, NULL, &len)) + return FALSE; + if (RequestedInformation & SACL_SECURITY_INFORMATION) + if (!DumpSacl(SecurityDescriptor, NULL, &len)) + return FALSE; + + wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR)); + if (RequestedInformation & OWNER_SECURITY_INFORMATION) + if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) + return FALSE; + if (RequestedInformation & GROUP_SECURITY_INFORMATION) + if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) + return FALSE; + if (RequestedInformation & DACL_SECURITY_INFORMATION) + if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) + return FALSE; + if (RequestedInformation & SACL_SECURITY_INFORMATION) + if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) + return FALSE; + *wptr = 0; + + TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len); + *OutputString = wstr; + if (OutputLen) + *OutputLen = strlenW(*OutputString)+1; + return TRUE; +} + +/****************************************************************************** + * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@] + */ +BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, ULONG *OutputLen) +{ + LPWSTR wstr; + ULONG len; + if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len)) + { + int lenA; + + lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL); + *OutputString = HeapAlloc(GetProcessHeap(), 0, lenA); + WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL); + LocalFree(wstr); + + if (OutputLen != NULL) + *OutputLen = lenA; + return TRUE; + } + else + { + *OutputString = NULL; + if (OutputLen) + *OutputLen = 0; + return FALSE; + } +} + /****************************************************************************** * ConvertStringSidToSidW [ADVAPI32.@] */ @@ -3538,37 +4000,19 @@ BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid) */ BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr ) { - DWORD sz, i; - LPWSTR str; - WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 }; - WCHAR subauthfmt[] = { '-','%','u',0 }; - SID* pisid=pSid; + DWORD len = 0; + LPWSTR wstr, wptr; TRACE("%p %p\n", pSid, pstr ); - if( !IsValidSid( pSid ) ) + len = 0; + if (!DumpSidNumeric(pSid, NULL, &len)) return FALSE; + wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR)); + DumpSidNumeric(pSid, &wptr, NULL); + *wptr = 0; - if (pisid->Revision != SDDL_REVISION) - return FALSE; - if (pisid->IdentifierAuthority.Value[0] || - pisid->IdentifierAuthority.Value[1]) - { - FIXME("not matching MS' bugs\n"); - return FALSE; - } - - sz = 14 + pisid->SubAuthorityCount * 11; - str = LocalAlloc( 0, sz*sizeof(WCHAR) ); - sprintfW( str, fmt, pisid->Revision, MAKELONG( - MAKEWORD( pisid->IdentifierAuthority.Value[5], - pisid->IdentifierAuthority.Value[4] ), - MAKEWORD( pisid->IdentifierAuthority.Value[3], - pisid->IdentifierAuthority.Value[2] ) ) ); - for( i=0; iSubAuthorityCount; i++ ) - sprintfW( str + strlenW(str), subauthfmt, pisid->SubAuthority[i] ); - *pstr = str; - + *pstr = wstr; return TRUE; } @@ -3761,7 +4205,7 @@ static DWORD ComputeStringSidSize(LPCWSTR StringSid) } else /* String constant format - Only available in winxp and above */ { - int i; + unsigned int i; for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2)) @@ -3840,12 +4284,12 @@ static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes) while (*StringSid) { + pisid->SubAuthority[i++] = atoiW(StringSid); + while (*StringSid && *StringSid != '-') StringSid++; if (*StringSid == '-') StringSid++; - - pisid->SubAuthority[i++] = atoiW(StringSid); } if (i != pisid->SubAuthorityCount) @@ -3855,7 +4299,7 @@ static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes) } else /* String constant format - Only available in winxp and above */ { - int i; + unsigned int i; pisid->Revision = SDDL_REVISION; for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index ce031ab3a27..82bd7ed6a47 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -2319,7 +2319,7 @@ BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName, if (!RegOpenKeyW(hscm->hkey, lpServiceName, &hkey)) { - INT len = lstrlenW(lpServiceName); + UINT len = lstrlenW(lpServiceName); BOOL r = FALSE; if ((*lpcchBuffer <= len) || (!lpDisplayName && *lpcchBuffer)) diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index 9756ca89700..c4b9ed472bf 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -53,6 +53,8 @@ typedef BOOL (WINAPI *fnConvertSidToStringSidA)( PSID pSid, LPSTR *str ); typedef BOOL (WINAPI *fnConvertStringSidToSidA)( LPCSTR str, PSID pSid ); static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR, DWORD, PSECURITY_DESCRIPTOR*, PULONG ); +static BOOL (WINAPI *pConvertSecurityDescriptorToStringSecurityDescriptorA)(PSECURITY_DESCRIPTOR, DWORD, + SECURITY_INFORMATION, LPSTR *, PULONG ); typedef BOOL (WINAPI *fnGetFileSecurityA)(LPCSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD); static DWORD (WINAPI *pGetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, @@ -106,6 +108,8 @@ static void init(void) hmod = GetModuleHandle("advapi32.dll"); pConvertStringSecurityDescriptorToSecurityDescriptorA = (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorA" ); + pConvertSecurityDescriptorToStringSecurityDescriptorA = + (void *)GetProcAddress(hmod, "ConvertSecurityDescriptorToStringSecurityDescriptorA" ); pGetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "GetNamedSecurityInfoA"); pSetEntriesInAclW = (void *)GetProcAddress(hmod, "SetEntriesInAclW"); @@ -148,6 +152,7 @@ static void test_sid(void) const char noSubAuthStr[] = "S-1-5"; unsigned int i; PSID psid = NULL; + SID *pisid; BOOL r; LPSTR str = NULL; @@ -185,6 +190,13 @@ static void test_sid(void) "expected GetLastError() is ERROR_INVALID_SID, got %d\n", GetLastError() ); + ok(pConvertStringSidToSidA("S-1-5-21-93476-23408-4576", &psid), "ConvertStringSidToSidA failed\n"); + pisid = (SID *)psid; + ok(pisid->SubAuthorityCount == 4, "Invalid sub authority count - expected 4, got %d\n", pisid->SubAuthorityCount); + ok(pisid->SubAuthority[0] == 21, "Invalid subauthority 0 - expceted 21, got %d\n", pisid->SubAuthority[0]); + ok(pisid->SubAuthority[3] == 4576, "Invalid subauthority 0 - expceted 4576, got %d\n", pisid->SubAuthority[3]); + LocalFree(str); + for( i = 0; i < sizeof(refs) / sizeof(refs[0]); i++ ) { PISID pisid; @@ -1848,19 +1860,16 @@ static void test_ConvertStringSecurityDescriptor(void) SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( "D:(A;;RPWPCCDCLCSWLODTCR;;;WD)", SDDL_REVISION_1, &pSD, NULL); - todo_wine ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); LocalFree(pSD); SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( "D:(A;;FAFRFWFX;;;WD)", SDDL_REVISION_1, &pSD, NULL); - todo_wine ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); LocalFree(pSD); SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( "D:(A;;KAKRKWKX;;;WD)", SDDL_REVISION_1, &pSD, NULL); - todo_wine ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); LocalFree(pSD); SetLastError(0xdeadbeef); @@ -1894,6 +1903,102 @@ static void test_ConvertStringSecurityDescriptor(void) GetLastError()); } +static void test_ConvertSecurityDescriptorToString() +{ + SECURITY_DESCRIPTOR desc; + SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION; + LPSTR string; + DWORD size; + PSID psid, psid2; + PACL pacl; + char sid_buf[256]; + char acl_buf[8192]; + ULONG len; + + if (!pConvertSecurityDescriptorToStringSecurityDescriptorA) + { + skip("ConvertSecurityDescriptorToStringSecurityDescriptor is not available\n"); + return; + } + +/* It seems Windows XP add an extra character to the length of the string for each ACE in an ACL. We + * don't replicate this feature so we only test len >= strlen+1. */ +#define CHECK_RESULT_AND_FREE(exp_str) \ + ok(strcmp(string, (exp_str)) == 0, "String mismatch (expected \"%s\", got \"%s\")\n", (exp_str), string); \ + ok(len >= (strlen(exp_str) + 1), "Length mismatch (expected %d, got %d)\n", strlen(exp_str) + 1, len); \ + LocalFree(string); + + InitializeSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE(""); + + size = 4096; + CreateWellKnownSid(WinLocalSid, NULL, sid_buf, &size); + SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, FALSE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:S-1-2-0"); + + SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, TRUE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:S-1-2-0"); + + size = sizeof(sid_buf); + CreateWellKnownSid(WinLocalSystemSid, NULL, sid_buf, &size); + SetSecurityDescriptorOwner(&desc, (PSID)sid_buf, TRUE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SY"); + + ConvertStringSidToSid("S-1-5-21-93476-23408-4576", &psid); + SetSecurityDescriptorGroup(&desc, psid, TRUE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576"); + + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, GROUP_SECURITY_INFORMATION, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576"); + + pacl = (PACL)acl_buf; + InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION); + SetSecurityDescriptorDacl(&desc, TRUE, pacl, TRUE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:"); + + SetSecurityDescriptorDacl(&desc, TRUE, pacl, FALSE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:"); + + ConvertStringSidToSid("S-1-5-6", &psid2); + AddAccessAllowedAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, 0xf0000000, psid2); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)"); + + AddAccessAllowedAceEx(pacl, ACL_REVISION, INHERIT_ONLY_ACE|INHERITED_ACE, 0x00000003, psid2); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)"); + + AddAccessDeniedAceEx(pacl, ACL_REVISION, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE, 0xffffffff, psid); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"); + + + pacl = (PACL)acl_buf; + InitializeAcl(pacl, sizeof(acl_buf), ACL_REVISION); + SetSecurityDescriptorSacl(&desc, TRUE, pacl, FALSE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:"); + + SetSecurityDescriptorDacl(&desc, TRUE, NULL, FALSE); + AddAuditAccessAceEx(pacl, ACL_REVISION, VALID_INHERIT_FLAGS, KEY_READ|KEY_WRITE, psid2, TRUE, TRUE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)"); + + AddAuditAccessAceEx(pacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, FILE_GENERIC_READ|FILE_GENERIC_WRITE, psid2, TRUE, FALSE); + ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(&desc, SDDL_REVISION_1, sec_info, &string, &len), "Convertion failed\n"); + CHECK_RESULT_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)"); + + +#undef CHECK_RESULT_AND_FREE +} + START_TEST(security) { init(); @@ -1917,4 +2022,5 @@ START_TEST(security) test_SetEntriesInAcl(); test_GetNamedSecurityInfoA(); test_ConvertStringSecurityDescriptor(); + test_ConvertSecurityDescriptorToString(); } diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index 7aea90659bf..bfb535d7584 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -727,7 +727,7 @@ static void test_sequence(void) static const CHAR servicename [] = "Winetest"; static const CHAR displayname [] = "Winetest dummy service"; static const CHAR pathname [] = "we_dont_care.exe"; - static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0\0"; + static const CHAR dependencies[] = "Master1\0Master2\0+MasterGroup1\0"; static const CHAR password [] = ""; static const CHAR empty [] = ""; static const CHAR localsystem [] = "LocalSystem"; diff --git a/dlls/comcat/regsvr.c b/dlls/comcat/regsvr.c index 1a2bb686045..21a7597c73a 100644 --- a/dlls/comcat/regsvr.c +++ b/dlls/comcat/regsvr.c @@ -101,8 +101,6 @@ static LONG register_key_defvalueW(HKEY base, WCHAR const *name, WCHAR const *value); static LONG register_key_defvalueA(HKEY base, WCHAR const *name, char const *value); -static LONG recursive_delete_key(HKEY key); - /*********************************************************************** * register_interfaces @@ -189,22 +187,12 @@ static HRESULT unregister_interfaces(struct regsvr_interface const *list) for (; res == ERROR_SUCCESS && list->iid; ++list) { WCHAR buf[39]; - HKEY iid_key; StringFromGUID2(list->iid, buf, 39); - res = RegOpenKeyExW(interface_key, buf, 0, - KEY_READ | KEY_WRITE, &iid_key); - if (res == ERROR_FILE_NOT_FOUND) { - res = ERROR_SUCCESS; - continue; - } - if (res != ERROR_SUCCESS) goto error_close_interface_key; - res = recursive_delete_key(iid_key); - RegCloseKey(iid_key); - if (res != ERROR_SUCCESS) goto error_close_interface_key; + res = RegDeleteTreeW(interface_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; } -error_close_interface_key: RegCloseKey(interface_key); error_return: return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; @@ -287,23 +275,12 @@ static HRESULT unregister_coclasses(struct regsvr_coclass const *list) for (; res == ERROR_SUCCESS && list->clsid; ++list) { WCHAR buf[39]; - HKEY clsid_key; StringFromGUID2(list->clsid, buf, 39); - res = RegOpenKeyExW(coclass_key, buf, 0, - KEY_READ | KEY_WRITE, &clsid_key); - if (res == ERROR_FILE_NOT_FOUND) { - res = ERROR_SUCCESS; - continue; - } - if (res != ERROR_SUCCESS) goto error_close_coclass_key; - res = recursive_delete_key(clsid_key); - RegCloseKey(clsid_key); - if (res != ERROR_SUCCESS) goto error_close_coclass_key; + res = RegDeleteTreeW(coclass_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; } -error_close_coclass_key: - RegCloseKey(coclass_key); error_return: return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; } @@ -360,38 +337,6 @@ static LONG register_key_defvalueA( } /*********************************************************************** - * recursive_delete_key - */ -static LONG recursive_delete_key(HKEY key) -{ - LONG res; - WCHAR subkey_name[MAX_PATH]; - DWORD cName; - HKEY subkey; - - for (;;) { - cName = sizeof(subkey_name) / sizeof(WCHAR); - res = RegEnumKeyExW(key, 0, subkey_name, &cName, - NULL, NULL, NULL, NULL); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - res = ERROR_SUCCESS; /* presumably we're done enumerating */ - break; - } - res = RegOpenKeyExW(key, subkey_name, 0, - KEY_READ | KEY_WRITE, &subkey); - if (res == ERROR_FILE_NOT_FOUND) continue; - if (res != ERROR_SUCCESS) break; - - res = recursive_delete_key(subkey); - RegCloseKey(subkey); - if (res != ERROR_SUCCESS) break; - } - - if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); - return res; -} - -/*********************************************************************** * coclass list */ static struct regsvr_coclass const coclass_list[] = { diff --git a/dlls/comdlg32/tests/printdlg.c b/dlls/comdlg32/tests/printdlg.c index 7e39dad4a4f..6827cb0f0ab 100644 --- a/dlls/comdlg32/tests/printdlg.c +++ b/dlls/comdlg32/tests/printdlg.c @@ -1,7 +1,7 @@ /* * Unit test suite for comdlg32 API functions: printer dialogs * - * Copyright 2006 Detlef Riekenberg + * Copyright 2006-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 @@ -33,6 +33,10 @@ #include "wine/test.h" +/* ######## */ + +static const CHAR emptyA[] = ""; +static const CHAR PrinterPortsA[] = "PrinterPorts"; /* ######## */ @@ -73,16 +77,16 @@ static void test_PageSetupDlgA(void) pDlg->Flags = PSD_RETURNDEFAULT; SetLastError(0xdeadbeef); res = PageSetupDlgA(pDlg); - trace("after pagesetupdlga res = %d, le %d, ext error 0x%x\n", - res, GetLastError(), CommDlgExtendedError()); ok( res || (CommDlgExtendedError() == PDERR_NODEFAULTPRN), "returned %u with %u and 0x%x (expected '!= 0' or '0' and " "PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError()); + if (!res && (CommDlgExtendedError() == PDERR_NODEFAULTPRN)) { - skip("No printer configured.\n"); - HeapFree(GetProcessHeap(), 0, pDlg); - return; + skip("No printer configured.\n"); + HeapFree(GetProcessHeap(), 0, pDlg); + return; } + ok( pDlg->hDevMode && pDlg->hDevNames, "got %p and %p (expected '!= NULL' for both)\n", pDlg->hDevMode, pDlg->hDevNames); @@ -100,6 +104,12 @@ static void test_PrintDlgA(void) { DWORD res; LPPRINTDLGA pDlg; + DEVNAMES *pDevNames; + LPCSTR driver; + LPCSTR device; + LPCSTR port; + CHAR buffer[MAX_PATH]; + LPSTR ptr; pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PRINTDLGA)) * 2); @@ -140,6 +150,62 @@ static void test_PrintDlgA(void) "returned %d with 0x%x and 0x%x (expected '!= 0' or '0' and " "PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError()); + if (!res && (CommDlgExtendedError() == PDERR_NODEFAULTPRN)) { + skip("No printer configured.\n"); + HeapFree(GetProcessHeap(), 0, pDlg); + return; + } + + ok(pDlg->hDevNames != NULL, "(expected '!= NULL')\n"); + pDevNames = GlobalLock(pDlg->hDevNames); + ok(pDevNames != NULL, "(expected '!= NULL')\n"); + + if (pDevNames) { + ok(pDevNames->wDriverOffset, "(expected '!= 0' for wDriverOffset)\n"); + ok(pDevNames->wDeviceOffset, "(expected '!= 0' for wDeviceOffset)\n"); + ok(pDevNames->wOutputOffset, "(expected '!= 0' for wOutputOffset)\n"); + ok(pDevNames->wDefault == DN_DEFAULTPRN, "got 0x%x (expected DN_DEFAULTPRN)\n", pDevNames->wDefault); + + driver = (LPCSTR)pDevNames + pDevNames->wDriverOffset; + device = (LPCSTR)pDevNames + pDevNames->wDeviceOffset; + port = (LPCSTR)pDevNames + pDevNames->wOutputOffset; + trace("driver '%s' device '%s' port '%s'\n", driver, device, port); + + /* The Driver Entry does not include a Path */ + ptr = strrchr(driver, '\\'); + todo_wine { + ok( ptr == NULL, "got %p for '%s' (expected NULL for a simple name)\n", ptr, driver); + } + + /* The Driver Entry does not have an extension (fixed to ".drv") */ + ptr = strrchr(driver, '.'); + todo_wine { + ok( ptr == NULL, "got %p for '%s' (expected NULL for no extension)\n", ptr, driver); + } + + + buffer[0] = '\0'; + SetLastError(0xdeadbeef); + res = GetProfileStringA(PrinterPortsA, device, emptyA, buffer, sizeof(buffer)); + ptr = strchr(buffer, ','); + todo_wine { + ok( (res > 1) && (ptr != NULL), + "got %u with %u and %p for '%s' (expected '>1' and '!= NULL')\n", + res, GetLastError(), ptr, buffer); + } + + if (ptr) ptr[0] = '\0'; + todo_wine { + ok( lstrcmpiA(driver, buffer) == 0, + "got driver '%s' (expected '%s')\n", driver, buffer); + } + + } + + GlobalUnlock(pDlg->hDevNames); + + GlobalFree(pDlg->hDevMode); + GlobalFree(pDlg->hDevNames); HeapFree(GetProcessHeap(), 0, pDlg); } diff --git a/dlls/crypt32/Makefile.in b/dlls/crypt32/Makefile.in index b7319bf1725..47ea46922a1 100644 --- a/dlls/crypt32/Makefile.in +++ b/dlls/crypt32/Makefile.in @@ -6,6 +6,7 @@ VPATH = @srcdir@ MODULE = crypt32.dll IMPORTLIB = libcrypt32.$(IMPLIBEXT) IMPORTS = user32 advapi32 kernel32 ntdll +DELAYIMPORTS = imagehlp C_SRCS = \ base64.c \ @@ -19,6 +20,7 @@ C_SRCS = \ filestore.c \ main.c \ msg.c \ + object.c \ oid.c \ proplist.c \ protectdata.c \ diff --git a/dlls/crypt32/main.c b/dlls/crypt32/main.c index db1744720de..f10a9c9b2bb 100644 --- a/dlls/crypt32/main.c +++ b/dlls/crypt32/main.c @@ -229,16 +229,3 @@ BOOL WINAPI CryptFormatObject(DWORD dwCertEncodingType, DWORD dwFormatType, debugstr_a(lpszStructType), pbEncoded, cbEncoded, pbFormat, pcbFormat); return FALSE; } - -BOOL WINAPI CryptQueryObject(DWORD dwObjectType, const void* pvObject, - DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags, - DWORD dwFlags, DWORD* pdwMsgAndCertEncodingType, DWORD* pdwContentType, - DWORD* pdwFormatType, HCERTSTORE* phCertStore, HCRYPTMSG* phMsg, - const void** ppvContext) -{ - FIXME( "%08x %p %08x %08x %08x %p %p %p %p %p %p\n", dwObjectType, - pvObject, dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags, - dwFlags, pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, - phCertStore, phMsg, ppvContext); - return FALSE; -} diff --git a/dlls/crypt32/object.c b/dlls/crypt32/object.c new file mode 100644 index 00000000000..e12ace37a8c --- /dev/null +++ b/dlls/crypt32/object.c @@ -0,0 +1,471 @@ +/* + * crypt32 Crypt*Object functions + * + * Copyright 2007 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include +#include "windef.h" +#include "winbase.h" +#include "wincrypt.h" +#include "imagehlp.h" +#include "crypt32_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(crypt); + +static BOOL CRYPT_ReadBlobFromFile(LPCWSTR fileName, PCERT_BLOB blob) +{ + BOOL ret = FALSE; + HANDLE file; + + TRACE("%s\n", debugstr_w(fileName)); + + file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, NULL); + if (file != INVALID_HANDLE_VALUE) + { + ret = TRUE; + blob->cbData = GetFileSize(file, NULL); + if (blob->cbData) + { + blob->pbData = CryptMemAlloc(blob->cbData); + if (blob->pbData) + { + DWORD read; + + ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL); + } + } + CloseHandle(file); + } + TRACE("returning %d\n", ret); + return ret; +} + +static BOOL CRYPT_QueryContextObject(DWORD dwObjectType, const void *pvObject, + DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType, + DWORD *pdwContentType, HCERTSTORE *phCertStore, const void **ppvContext) +{ + CERT_BLOB fileBlob; + const CERT_BLOB *blob; + HCERTSTORE store; + DWORD contentType; + BOOL ret; + + switch (dwObjectType) + { + case CERT_QUERY_OBJECT_FILE: + /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so + * just read the file directly + */ + ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob); + blob = &fileBlob; + break; + case CERT_QUERY_OBJECT_BLOB: + blob = (const CERT_BLOB *)pvObject; + ret = TRUE; + break; + default: + SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ + ret = FALSE; + } + if (!ret) + return FALSE; + + store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + ret = FALSE; + if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) + { + ret = pCertInterface->addEncodedToStore(store, X509_ASN_ENCODING, + blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext); + if (ret) + contentType = CERT_QUERY_CONTENT_CERT; + } + if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL)) + { + ret = pCRLInterface->addEncodedToStore(store, X509_ASN_ENCODING, + blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext); + if (ret) + contentType = CERT_QUERY_CONTENT_CRL; + } + if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL)) + { + ret = pCTLInterface->addEncodedToStore(store, X509_ASN_ENCODING, + blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext); + if (ret) + contentType = CERT_QUERY_CONTENT_CTL; + } + if (ret) + { + if (pdwMsgAndCertEncodingType) + *pdwMsgAndCertEncodingType = X509_ASN_ENCODING; + if (pdwContentType) + *pdwContentType = contentType; + if (phCertStore) + *phCertStore = CertDuplicateStore(store); + } + CertCloseStore(store, 0); + if (blob == &fileBlob) + CryptMemFree(blob->pbData); + TRACE("returning %d\n", ret); + return ret; +} + +static BOOL CRYPT_QuerySerializedContextObject(DWORD dwObjectType, + const void *pvObject, DWORD dwExpectedContentTypeFlags, + DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, + HCERTSTORE *phCertStore, const void **ppvContext) +{ + CERT_BLOB fileBlob; + const CERT_BLOB *blob; + const WINE_CONTEXT_INTERFACE *contextInterface = NULL; + const void *context; + DWORD contextType; + BOOL ret; + + switch (dwObjectType) + { + case CERT_QUERY_OBJECT_FILE: + /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so + * just read the file directly + */ + ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob); + blob = &fileBlob; + break; + case CERT_QUERY_OBJECT_BLOB: + blob = (const CERT_BLOB *)pvObject; + ret = TRUE; + break; + default: + SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ + ret = FALSE; + } + if (!ret) + return FALSE; + + context = CRYPT_ReadSerializedElement(blob->pbData, blob->cbData, + CERT_STORE_ALL_CONTEXT_FLAG, &contextType); + if (context) + { + DWORD contentType, certStoreOffset; + + ret = TRUE; + switch (contextType) + { + case CERT_STORE_CERTIFICATE_CONTEXT: + contextInterface = pCertInterface; + contentType = CERT_QUERY_CONTENT_SERIALIZED_CERT; + certStoreOffset = offsetof(CERT_CONTEXT, hCertStore); + if (!(dwExpectedContentTypeFlags & + CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT)) + { + SetLastError(ERROR_INVALID_DATA); + ret = FALSE; + goto end; + } + break; + case CERT_STORE_CRL_CONTEXT: + contextInterface = pCRLInterface; + contentType = CERT_QUERY_CONTENT_SERIALIZED_CRL; + certStoreOffset = offsetof(CRL_CONTEXT, hCertStore); + if (!(dwExpectedContentTypeFlags & + CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL)) + { + SetLastError(ERROR_INVALID_DATA); + ret = FALSE; + goto end; + } + break; + case CERT_STORE_CTL_CONTEXT: + contextInterface = pCTLInterface; + contentType = CERT_QUERY_CONTENT_SERIALIZED_CTL; + certStoreOffset = offsetof(CTL_CONTEXT, hCertStore); + if (!(dwExpectedContentTypeFlags & + CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL)) + { + SetLastError(ERROR_INVALID_DATA); + ret = FALSE; + goto end; + } + break; + default: + SetLastError(ERROR_INVALID_DATA); + ret = FALSE; + goto end; + } + if (pdwMsgAndCertEncodingType) + *pdwMsgAndCertEncodingType = X509_ASN_ENCODING; + if (pdwContentType) + *pdwContentType = contentType; + if (phCertStore) + *phCertStore = CertDuplicateStore( + *(HCERTSTORE *)((const BYTE *)context + certStoreOffset)); + if (ppvContext) + *ppvContext = contextInterface->duplicate(context); + } + +end: + if (contextInterface && context) + contextInterface->free(context); + if (blob == &fileBlob) + CryptMemFree(blob->pbData); + TRACE("returning %d\n", ret); + return ret; +} + +static BOOL CRYPT_QuerySerializedStoreObject(DWORD dwObjectType, + const void *pvObject, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, + HCERTSTORE *phCertStore, HCRYPTMSG *phMsg) +{ + LPCWSTR fileName = (LPCWSTR)pvObject; + HANDLE file; + BOOL ret = FALSE; + + if (dwObjectType != CERT_QUERY_OBJECT_FILE) + { + FIXME("unimplemented for non-file type %d\n", dwObjectType); + SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ + return FALSE; + } + TRACE("%s\n", debugstr_w(fileName)); + file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, NULL); + if (file != INVALID_HANDLE_VALUE) + { + HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + + ret = CRYPT_ReadSerializedFile(file, store); + if (ret) + { + if (pdwMsgAndCertEncodingType) + *pdwMsgAndCertEncodingType = X509_ASN_ENCODING; + if (pdwContentType) + *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE; + if (phCertStore) + *phCertStore = CertDuplicateStore(store); + } + CertCloseStore(store, 0); + CloseHandle(file); + } + TRACE("returning %d\n", ret); + return ret; +} + +/* Used to decode non-embedded messages */ +static BOOL CRYPT_QueryMessageObject(DWORD dwObjectType, const void *pvObject, + DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType, + DWORD *pdwContentType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg) +{ + CERT_BLOB fileBlob; + const CERT_BLOB *blob; + BOOL ret; + HCRYPTMSG msg = NULL; + DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING; + + switch (dwObjectType) + { + case CERT_QUERY_OBJECT_FILE: + /* This isn't an embedded PKCS7 message, so just read the file + * directly + */ + ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob); + blob = &fileBlob; + break; + case CERT_QUERY_OBJECT_BLOB: + blob = (const CERT_BLOB *)pvObject; + ret = TRUE; + break; + default: + SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */ + ret = FALSE; + } + if (!ret) + return FALSE; + + ret = FALSE; + if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) + { + msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_SIGNED, 0, NULL, NULL); + if (msg) + { + ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); + if (!ret) + { + CryptMsgClose(msg); + msg = NULL; + } + } + if (msg && pdwContentType) + *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED; + } + if (!ret && + (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)) + { + msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_DATA, 0, NULL, NULL); + if (msg) + { + ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE); + if (!ret) + { + CryptMsgClose(msg); + msg = NULL; + } + } + if (msg && pdwContentType) + *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED; + } + if (pdwMsgAndCertEncodingType) + *pdwMsgAndCertEncodingType = encodingType; + if (msg) + { + if (phMsg) + *phMsg = msg; + if (phCertStore) + *phCertStore = CertOpenStore(CERT_STORE_PROV_MSG, encodingType, 0, + 0, msg); + } + if (blob == &fileBlob) + CryptMemFree(blob->pbData); + TRACE("returning %d\n", ret); + return ret; +} + +static BOOL CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType, + const void *pvObject, DWORD dwExpectedContentTypeFlags, + DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, + HCERTSTORE *phCertStore, HCRYPTMSG *phMsg) +{ + HANDLE file; + BOOL ret = FALSE; + + if (dwObjectType != CERT_QUERY_OBJECT_FILE) + { + FIXME("don't know what to do for type %d embedded signed messages\n", + dwObjectType); + SetLastError(E_INVALIDARG); + return FALSE; + } + file = CreateFileW((LPCWSTR)pvObject, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file != INVALID_HANDLE_VALUE) + { + CERT_BLOB blob; + + ret = ImageGetCertificateData(file, 0, NULL, &blob.cbData); + if (ret) + { + blob.pbData = HeapAlloc(GetProcessHeap(), 0, blob.cbData); + if (blob.pbData) + { + ret = ImageGetCertificateData(file, 0, + (WIN_CERTIFICATE *)blob.pbData, &blob.cbData); + if (ret) + { + ret = CRYPT_QueryMessageObject(CERT_QUERY_OBJECT_BLOB, + &blob, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED, + pdwMsgAndCertEncodingType, NULL, phCertStore, phMsg); + if (ret && pdwContentType) + *pdwContentType = CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED; + } + HeapFree(GetProcessHeap(), 0, blob.pbData); + } + } + CloseHandle(file); + } + TRACE("returning %d\n", ret); + return ret; +} + +BOOL WINAPI CryptQueryObject(DWORD dwObjectType, const void *pvObject, + DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags, + DWORD dwFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType, + DWORD *pdwFormatType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg, + const void **ppvContext) +{ + static const DWORD unimplementedTypes = + CERT_QUERY_CONTENT_FLAG_PKCS10 | CERT_QUERY_CONTENT_FLAG_PFX | + CERT_QUERY_CONTENT_FLAG_CERT_PAIR; + BOOL ret = TRUE; + + TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n", + dwObjectType, pvObject, dwExpectedContentTypeFlags, + dwExpectedFormatTypeFlags, dwFlags, pdwMsgAndCertEncodingType, + pdwContentType, pdwFormatType, phCertStore, phMsg, ppvContext); + + if (dwExpectedContentTypeFlags & unimplementedTypes) + WARN("unimplemented for types %08x\n", + dwExpectedContentTypeFlags & unimplementedTypes); + if (!(dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY)) + { + FIXME("unimplemented for anything but binary\n"); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + if (pdwFormatType) + *pdwFormatType = CERT_QUERY_FORMAT_BINARY; + + if (phCertStore) + *phCertStore = NULL; + if (phMsg) + *phMsg = NULL; + if (ppvContext) + *ppvContext = NULL; + + ret = FALSE; + if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) || + (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL) || + (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL)) + { + ret = CRYPT_QueryContextObject(dwObjectType, pvObject, + dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType, + phCertStore, ppvContext); + } + if (!ret && + (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE)) + { + ret = CRYPT_QuerySerializedStoreObject(dwObjectType, pvObject, + pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg); + } + if (!ret && + ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT) || + (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL) || + (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL))) + { + ret = CRYPT_QuerySerializedContextObject(dwObjectType, pvObject, + dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType, + phCertStore, ppvContext); + } + if (!ret && + ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) || + (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))) + { + ret = CRYPT_QueryMessageObject(dwObjectType, pvObject, + dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType, + phCertStore, phMsg); + } + if (!ret && + (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED)) + { + ret = CRYPT_QueryEmbeddedMessageObject(dwObjectType, pvObject, + dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType, + phCertStore, phMsg); + } + TRACE("returning %d\n"); + return ret; +} diff --git a/dlls/d3dxof/regsvr.c b/dlls/d3dxof/regsvr.c index 7c90bd60ee2..34c5827fc20 100644 --- a/dlls/d3dxof/regsvr.c +++ b/dlls/d3dxof/regsvr.c @@ -118,9 +118,6 @@ static LONG register_key_defvalueA(HKEY base, WCHAR const *name, static LONG register_progid(WCHAR const *clsid, char const *progid, char const *curver_progid, char const *name, char const *extra); -static LONG recursive_delete_key(HKEY key); -static LONG recursive_delete_keyA(HKEY base, char const *name); -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name); /*********************************************************************** * register_interfaces @@ -209,7 +206,8 @@ static HRESULT unregister_interfaces(struct regsvr_interface const *list) WCHAR buf[39]; StringFromGUID2(list->iid, buf, 39); - res = recursive_delete_keyW(interface_key, buf); + res = RegDeleteTreeW(interface_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; } RegCloseKey(interface_key); @@ -316,16 +314,19 @@ static HRESULT unregister_coclasses(struct regsvr_coclass const *list) WCHAR buf[39]; StringFromGUID2(list->clsid, buf, 39); - res = recursive_delete_keyW(coclass_key, buf); + res = RegDeleteTreeW(coclass_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; if (list->progid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid); + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } if (list->viprogid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid); + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } } @@ -438,70 +439,6 @@ error_close_progid_key: } /*********************************************************************** - * recursive_delete_key - */ -static LONG recursive_delete_key(HKEY key) -{ - LONG res; - WCHAR subkey_name[MAX_PATH]; - DWORD cName; - HKEY subkey; - - for (;;) { - cName = sizeof(subkey_name) / sizeof(WCHAR); - res = RegEnumKeyExW(key, 0, subkey_name, &cName, - NULL, NULL, NULL, NULL); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - res = ERROR_SUCCESS; /* presumably we're done enumerating */ - break; - } - res = RegOpenKeyExW(key, subkey_name, 0, - KEY_READ | KEY_WRITE, &subkey); - if (res == ERROR_FILE_NOT_FOUND) continue; - if (res != ERROR_SUCCESS) break; - - res = recursive_delete_key(subkey); - RegCloseKey(subkey); - if (res != ERROR_SUCCESS) break; - } - - if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); - return res; -} - -/*********************************************************************** - * recursive_delete_keyA - */ -static LONG recursive_delete_keyA(HKEY base, char const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * recursive_delete_keyW - */ -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** * coclass list */ static struct regsvr_coclass const coclass_list[] = { diff --git a/dlls/ddraw/regsvr.c b/dlls/ddraw/regsvr.c index 877c8a27717..4371e62267e 100644 --- a/dlls/ddraw/regsvr.c +++ b/dlls/ddraw/regsvr.c @@ -105,9 +105,6 @@ static LONG register_key_defvalueW(HKEY base, WCHAR const *name, WCHAR const *value); static LONG register_key_defvalueA(HKEY base, WCHAR const *name, char const *value); -static LONG recursive_delete_key(HKEY key); -static LONG recursive_delete_keyA(HKEY base, char const *name); -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name); /*********************************************************************** * register_interfaces @@ -196,7 +193,8 @@ static HRESULT unregister_interfaces(struct regsvr_interface const *list) WCHAR buf[39]; StringFromGUID2(list->iid, buf, 39); - res = recursive_delete_keyW(interface_key, buf); + res = RegDeleteTreeW(interface_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; } RegCloseKey(interface_key); @@ -306,11 +304,13 @@ static HRESULT unregister_coclasses(struct regsvr_coclass const *list) WCHAR buf[39]; StringFromGUID2(list->clsid, buf, 39); - res = recursive_delete_keyW(coclass_key, buf); + res = RegDeleteTreeW(coclass_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; if (list->progid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid); + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } } @@ -373,70 +373,6 @@ static LONG register_key_defvalueA( } /*********************************************************************** - * recursive_delete_key - */ -static LONG recursive_delete_key(HKEY key) -{ - LONG res; - WCHAR subkey_name[MAX_PATH]; - DWORD cName; - HKEY subkey; - - for (;;) { - cName = sizeof(subkey_name) / sizeof(WCHAR); - res = RegEnumKeyExW(key, 0, subkey_name, &cName, - NULL, NULL, NULL, NULL); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - res = ERROR_SUCCESS; /* presumably we're done enumerating */ - break; - } - res = RegOpenKeyExW(key, subkey_name, 0, - KEY_READ | KEY_WRITE, &subkey); - if (res == ERROR_FILE_NOT_FOUND) continue; - if (res != ERROR_SUCCESS) break; - - res = recursive_delete_key(subkey); - RegCloseKey(subkey); - if (res != ERROR_SUCCESS) break; - } - - if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); - return res; -} - -/*********************************************************************** - * recursive_delete_keyA - */ -static LONG recursive_delete_keyA(HKEY base, char const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * recursive_delete_keyW - */ -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** * coclass list */ diff --git a/dlls/ddrawex/regsvr.c b/dlls/ddrawex/regsvr.c index 0e73abcbdbe..5467f6b3403 100644 --- a/dlls/ddrawex/regsvr.c +++ b/dlls/ddrawex/regsvr.c @@ -94,9 +94,6 @@ static LONG register_key_defvalueW(HKEY base, WCHAR const *name, WCHAR const *value); static LONG register_key_defvalueA(HKEY base, WCHAR const *name, char const *value); -static LONG recursive_delete_key(HKEY key); -static LONG recursive_delete_keyA(HKEY base, char const *name); -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name); /*********************************************************************** * register_coclasses @@ -200,11 +197,13 @@ static HRESULT unregister_coclasses(struct regsvr_coclass const *list) WCHAR buf[39]; StringFromGUID2(list->clsid, buf, 39); - res = recursive_delete_keyW(coclass_key, buf); + res = RegDeleteTreeW(coclass_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; if (list->progid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid); + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } } @@ -256,70 +255,6 @@ static LONG register_key_defvalueA( } /*********************************************************************** - * recursive_delete_key - */ -static LONG recursive_delete_key(HKEY key) -{ - LONG res; - WCHAR subkey_name[MAX_PATH]; - DWORD cName; - HKEY subkey; - - for (;;) { - cName = sizeof(subkey_name) / sizeof(WCHAR); - res = RegEnumKeyExW(key, 0, subkey_name, &cName, - NULL, NULL, NULL, NULL); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - res = ERROR_SUCCESS; /* presumably we're done enumerating */ - break; - } - res = RegOpenKeyExW(key, subkey_name, 0, - KEY_READ | KEY_WRITE, &subkey); - if (res == ERROR_FILE_NOT_FOUND) continue; - if (res != ERROR_SUCCESS) break; - - res = recursive_delete_key(subkey); - RegCloseKey(subkey); - if (res != ERROR_SUCCESS) break; - } - - if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); - return res; -} - -/*********************************************************************** - * recursive_delete_keyA - */ -static LONG recursive_delete_keyA(HKEY base, char const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * recursive_delete_keyW - */ -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** * coclass list */ diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 10e31cd412c..170d8fdeee6 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -32,6 +32,7 @@ #include "wine/unicode.h" #include "windef.h" #include "winbase.h" +#include "winreg.h" #include "winuser.h" #include "winerror.h" #include "dinput.h" @@ -216,6 +217,56 @@ void _dump_DIDATAFORMAT(const DIDATAFORMAT *df) { } } +/****************************************************************************** + * Get the default and the app-specific config keys. + */ +BOOL get_app_key(HKEY *defkey, HKEY *appkey) +{ + char buffer[MAX_PATH+16]; + DWORD len; + + *appkey = 0; + + /* @@ Wine registry key: HKCU\Software\Wine\DirectInput */ + if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\DirectInput", defkey)) + *defkey = 0; + + len = GetModuleFileNameA(0, buffer, MAX_PATH); + if (len && len < MAX_PATH) + { + HKEY tmpkey; + + /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\DirectInput */ + if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey)) + { + char *p, *appname = buffer; + if ((p = strrchr(appname, '/'))) appname = p + 1; + if ((p = strrchr(appname, '\\'))) appname = p + 1; + strcat(appname, "\\DirectInput"); + + if (RegOpenKeyA(tmpkey, appname, appkey)) appkey = 0; + RegCloseKey(tmpkey); + } + } + + return *defkey || *appkey; +} + +/****************************************************************************** + * Get a config key from either the app-specific or the default config + */ +DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name, + char *buffer, DWORD size ) +{ + if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) + return 0; + + if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) + return 0; + + return ERROR_FILE_NOT_FOUND; +} + /* Conversion between internal data buffer and external data buffer */ void fill_DataFormat(void *out, const void *in, const DataFormat *df) { int i; diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 6686577b13c..edd1f4bf4e9 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -72,6 +72,9 @@ struct IDirectInputDevice2AImpl DataFormat data_format; /* user data format and wine to user format converter */ }; +extern BOOL get_app_key(HKEY*, HKEY*); +extern DWORD get_config_key(HKEY, HKEY, const char*, char*, DWORD); + /* Routines to do DataFormat / WineFormat conversions */ extern void fill_DataFormat(void *out, const void *in, const DataFormat *df) ; extern HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *format); diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c index e15e32e128b..000837df83d 100644 --- a/dlls/dinput/joystick_linux.c +++ b/dlls/dinput/joystick_linux.c @@ -263,50 +263,17 @@ static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN } /* - * Get a config key from either the app-specific or the default config - */ - -static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name, - char *buffer, DWORD size ) -{ - if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) - return 0; - - if (defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE)buffer, &size )) - return 0; - - return ERROR_FILE_NOT_FOUND; -} - -/* * Setup the dinput options. */ static HRESULT setup_dinput_options(JoystickImpl * device) { char buffer[MAX_PATH+16]; - HKEY hkey, appkey = 0; - DWORD len; + HKEY hkey, appkey; buffer[MAX_PATH]='\0'; - /* @@ Wine registry key: HKCU\Software\Wine\DirectInput */ - if (RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\DirectInput", &hkey)) hkey = 0; - - len = GetModuleFileNameA( 0, buffer, MAX_PATH ); - if (len && len < MAX_PATH) { - HKEY tmpkey; - /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\DirectInput */ - if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey )) - { - char *p, *appname = buffer; - if ((p = strrchr( appname, '/' ))) appname = p + 1; - if ((p = strrchr( appname, '\\' ))) appname = p + 1; - strcat( appname, "\\DirectInput" ); - if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0; - RegCloseKey( tmpkey ); - } - } + get_app_key(&hkey, &appkey); /* get options */ diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c index 37ae4a78543..dba14183c09 100644 --- a/dlls/dinput/joystick_linuxinput.c +++ b/dlls/dinput/joystick_linuxinput.c @@ -58,6 +58,7 @@ #include "windef.h" #include "winbase.h" #include "winerror.h" +#include "winreg.h" #include "dinput.h" #include "dinput_private.h" @@ -316,6 +317,48 @@ static void find_joydevs(void) } } +static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, int id) +{ + DWORD dwSize = lpddi->dwSize; + + TRACE("%d %p\n", dwSize, lpddi); + memset(lpddi, 0, dwSize); + + lpddi->dwSize = dwSize; + lpddi->guidInstance = joydevs[id].guid; + lpddi->guidProduct = DInput_Wine_Joystick_Base_GUID; + lpddi->guidFFDriver = GUID_NULL; + + if (version >= 0x0800) + lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); + else + lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + + strcpy(lpddi->tszInstanceName, joydevs[id].name); + strcpy(lpddi->tszProductName, joydevs[id].device); +} + +static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, int id) +{ + DWORD dwSize = lpddi->dwSize; + + TRACE("%d %p\n", dwSize, lpddi); + memset(lpddi, 0, dwSize); + + lpddi->dwSize = dwSize; + lpddi->guidInstance = joydevs[id].guid; + lpddi->guidProduct = DInput_Wine_Joystick_Base_GUID; + lpddi->guidFFDriver = GUID_NULL; + + if (version >= 0x0800) + lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); + else + lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); + + MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszInstanceName, MAX_PATH); + MultiByteToWideChar(CP_ACP, 0, joydevs[id].device, -1, lpddi->tszProductName, MAX_PATH); +} + static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id) { find_joydevs(); @@ -335,17 +378,7 @@ static BOOL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN #endif if (!(dwFlags & DIEDFL_FORCEFEEDBACK) || joydevs[id].has_ff) { - lpddi->guidInstance = joydevs[id].guid; - lpddi->guidProduct = DInput_Wine_Joystick_Base_GUID; - - lpddi->guidFFDriver = GUID_NULL; - if (version >= 0x0800) - lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); - else - lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); - - strcpy(lpddi->tszInstanceName, joydevs[id].name); - strcpy(lpddi->tszProductName, joydevs[id].device); + fill_joystick_dideviceinstanceA(lpddi, version, id); return TRUE; } return FALSE; @@ -370,17 +403,7 @@ static BOOL joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTAN #endif if (!(dwFlags & DIEDFL_FORCEFEEDBACK) || joydevs[id].has_ff) { - lpddi->guidInstance = joydevs[id].guid; - lpddi->guidProduct = DInput_Wine_Joystick_Base_GUID; - - lpddi->guidFFDriver = GUID_NULL; - if (version >= 0x0800) - lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); - else - lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); - - MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszInstanceName, MAX_PATH); - MultiByteToWideChar(CP_ACP, 0, joydevs[id].device, -1, lpddi->tszProductName, MAX_PATH); + fill_joystick_dideviceinstanceW(lpddi, version, id); return TRUE; } return FALSE; @@ -391,21 +414,35 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm JoystickImpl* newDevice; LPDIDATAFORMAT df = NULL; int i, idx = 0; + char buffer[MAX_PATH+16]; + HKEY hkey, appkey; + LONG def_deadzone = -1; newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(JoystickImpl)); if (!newDevice) return NULL; - newDevice->base.lpVtbl = jvt; - newDevice->base.ref = 1; - memcpy(&newDevice->base.guid, rguid, sizeof(*rguid)); - InitializeCriticalSection(&newDevice->base.crit); - newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit"); - newDevice->joyfd = -1; - newDevice->base.dinput = dinput; - newDevice->joydev = &joydevs[index]; + newDevice->base.lpVtbl = jvt; + newDevice->base.ref = 1; + newDevice->base.guid = *rguid; + newDevice->base.dinput = dinput; + newDevice->joyfd = -1; + newDevice->joydev = &joydevs[index]; #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION - newDevice->ff_state = FF_STATUS_STOPPED; + newDevice->ff_state = FF_STATUS_STOPPED; #endif + InitializeCriticalSection(&newDevice->base.crit); + newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit"); + + /* get options */ + get_app_key(&hkey, &appkey); + + if (!get_config_key(hkey, appkey, "DefaultDeadZone", buffer, MAX_PATH)) + { + def_deadzone = atoi(buffer); + TRACE("setting default deadzone to: %d\n", def_deadzone); + } + if (appkey) RegCloseKey(appkey); + if (hkey) RegCloseKey(hkey); /* Create copy of default data format */ if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed; @@ -427,7 +464,8 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm newDevice->props[idx].lMin = 0; newDevice->props[idx].lMax = 0xffff; newDevice->props[idx].lSaturation = 0; - newDevice->props[idx].lDeadZone = MulDiv(newDevice->joydev->axes[i].flat, 0xffff, + newDevice->props[idx].lDeadZone = def_deadzone >= 0 ? def_deadzone : + MulDiv(newDevice->joydev->axes[i].flat, 0xffff, newDevice->props[idx].lDevMax - newDevice->props[idx].lDevMin); df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(newDevice->numAxes++) | DIDFT_ABSAXIS; @@ -1309,6 +1347,43 @@ static HRESULT WINAPI JoystickAImpl_EnumCreatedEffectObjects( return DI_OK; } +/****************************************************************************** + * GetDeviceInfo : get information about a device's identity + */ +static HRESULT WINAPI JoystickAImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8A iface, + LPDIDEVICEINSTANCEA pdidi) +{ + JoystickImpl *This = (JoystickImpl *)iface; + + TRACE("(%p) %p\n", This, pdidi); + + if (pdidi == NULL) return E_POINTER; + if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3A)) && + (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA))) + return DIERR_INVALIDPARAM; + + fill_joystick_dideviceinstanceA(pdidi, This->base.dinput->dwVersion, + get_joystick_index(&This->base.guid)); + return DI_OK; +} + +static HRESULT WINAPI JoystickWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, + LPDIDEVICEINSTANCEW pdidi) +{ + JoystickImpl *This = (JoystickImpl *)iface; + + TRACE("(%p) %p\n", This, pdidi); + + if (pdidi == NULL) return E_POINTER; + if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) && + (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW))) + return DIERR_INVALIDPARAM; + + fill_joystick_dideviceinstanceW(pdidi, This->base.dinput->dwVersion, + get_joystick_index(&This->base.guid)); + return DI_OK; +} + static const IDirectInputDevice8AVtbl JoystickAvt = { IDirectInputDevice2AImpl_QueryInterface, @@ -1326,7 +1401,7 @@ static const IDirectInputDevice8AVtbl JoystickAvt = IDirectInputDevice2AImpl_SetEventNotification, IDirectInputDevice2AImpl_SetCooperativeLevel, JoystickAImpl_GetObjectInfo, - IDirectInputDevice2AImpl_GetDeviceInfo, + JoystickAImpl_GetDeviceInfo, IDirectInputDevice2AImpl_RunControlPanel, IDirectInputDevice2AImpl_Initialize, JoystickAImpl_CreateEffect, @@ -1368,7 +1443,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt = XCAST(SetEventNotification)IDirectInputDevice2AImpl_SetEventNotification, XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel, JoystickWImpl_GetObjectInfo, - IDirectInputDevice2WImpl_GetDeviceInfo, + JoystickWImpl_GetDeviceInfo, XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel, XCAST(Initialize)IDirectInputDevice2AImpl_Initialize, XCAST(CreateEffect)JoystickAImpl_CreateEffect, diff --git a/dlls/dinput/regsvr.c b/dlls/dinput/regsvr.c index fed3aadeb98..ac1ffc1690d 100644 --- a/dlls/dinput/regsvr.c +++ b/dlls/dinput/regsvr.c @@ -115,9 +115,6 @@ static LONG register_key_defvalueA(HKEY base, WCHAR const *name, static LONG register_progid(WCHAR const *clsid, char const *progid, char const *curver_progid, char const *name, char const *extra); -static LONG recursive_delete_key(HKEY key); -static LONG recursive_delete_keyA(HKEY base, char const *name); -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name); /*********************************************************************** * register_interfaces @@ -206,7 +203,8 @@ static HRESULT unregister_interfaces(struct regsvr_interface const *list) WCHAR buf[39]; StringFromGUID2(list->iid, buf, 39); - res = recursive_delete_keyW(interface_key, buf); + res = RegDeleteTreeW(interface_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; } RegCloseKey(interface_key); @@ -313,16 +311,19 @@ static HRESULT unregister_coclasses(struct regsvr_coclass const *list) WCHAR buf[39]; StringFromGUID2(list->clsid, buf, 39); - res = recursive_delete_keyW(coclass_key, buf); + res = RegDeleteTreeW(coclass_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; if (list->progid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid); + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } if (list->viprogid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid); + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } } @@ -435,70 +436,6 @@ error_close_progid_key: } /*********************************************************************** - * recursive_delete_key - */ -static LONG recursive_delete_key(HKEY key) -{ - LONG res; - WCHAR subkey_name[MAX_PATH]; - DWORD cName; - HKEY subkey; - - for (;;) { - cName = sizeof(subkey_name) / sizeof(WCHAR); - res = RegEnumKeyExW(key, 0, subkey_name, &cName, - NULL, NULL, NULL, NULL); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - res = ERROR_SUCCESS; /* presumably we're done enumerating */ - break; - } - res = RegOpenKeyExW(key, subkey_name, 0, - KEY_READ | KEY_WRITE, &subkey); - if (res == ERROR_FILE_NOT_FOUND) continue; - if (res != ERROR_SUCCESS) break; - - res = recursive_delete_key(subkey); - RegCloseKey(subkey); - if (res != ERROR_SUCCESS) break; - } - - if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); - return res; -} - -/*********************************************************************** - * recursive_delete_keyA - */ -static LONG recursive_delete_keyA(HKEY base, char const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * recursive_delete_keyW - */ -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** * coclass list */ static struct regsvr_coclass const coclass_list[] = { diff --git a/dlls/dinput8/regsvr.c b/dlls/dinput8/regsvr.c index c278ed34702..3d8cdc9458a 100644 --- a/dlls/dinput8/regsvr.c +++ b/dlls/dinput8/regsvr.c @@ -93,9 +93,6 @@ static LONG register_key_defvalueW(HKEY base, WCHAR const *name, WCHAR const *value); static LONG register_key_defvalueA(HKEY base, WCHAR const *name, char const *value); -static LONG recursive_delete_key(HKEY key); -static LONG recursive_delete_keyA(HKEY base, char const *name); -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name); /*********************************************************************** * register_coclasses @@ -199,11 +196,13 @@ static HRESULT unregister_coclasses(struct regsvr_coclass const *list) WCHAR buf[39]; StringFromGUID2(list->clsid, buf, 39); - res = recursive_delete_keyW(coclass_key, buf); + res = RegDeleteTreeW(coclass_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; if (list->progid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid); + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } } @@ -255,70 +254,6 @@ static LONG register_key_defvalueA( } /*********************************************************************** - * recursive_delete_key - */ -static LONG recursive_delete_key(HKEY key) -{ - LONG res; - WCHAR subkey_name[MAX_PATH]; - DWORD cName; - HKEY subkey; - - for (;;) { - cName = sizeof(subkey_name) / sizeof(WCHAR); - res = RegEnumKeyExW(key, 0, subkey_name, &cName, - NULL, NULL, NULL, NULL); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - res = ERROR_SUCCESS; /* presumably we're done enumerating */ - break; - } - res = RegOpenKeyExW(key, subkey_name, 0, - KEY_READ | KEY_WRITE, &subkey); - if (res == ERROR_FILE_NOT_FOUND) continue; - if (res != ERROR_SUCCESS) break; - - res = recursive_delete_key(subkey); - RegCloseKey(subkey); - if (res != ERROR_SUCCESS) break; - } - - if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); - return res; -} - -/*********************************************************************** - * recursive_delete_keyA - */ -static LONG recursive_delete_keyA(HKEY base, char const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * recursive_delete_keyW - */ -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** * coclass list */ diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index 16886149f7e..27e17c2541e 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -3727,8 +3727,10 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections &sizeOfReturnBuffer ) != ERROR_SUCCESS ) { ERR(": missing GUID registry data members\n" ); + RegCloseKey(hkServiceProvider); continue; } + RegCloseKey(hkServiceProvider); /* FIXME: Check return types to ensure we're interpreting data right */ MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) ); @@ -3822,8 +3824,10 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections &sizeOfReturnBuffer ) != ERROR_SUCCESS ) { ERR(": missing GUID registry data members\n" ); + RegCloseKey(hkServiceProvider); continue; } + RegCloseKey(hkServiceProvider); /* FIXME: Check return types to ensure we're interpreting data right */ MultiByteToWideChar( CP_ACP, 0, returnBuffer, -1, buff, sizeof(buff)/sizeof(WCHAR) ); @@ -3861,6 +3865,7 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections &dwAddressBufferSize, TRUE ) ) != DP_OK ) { ERR( "can't create address: %s\n", DPLAYX_HresultToString( hr ) ); + HeapFree( GetProcessHeap(), 0, lpAddressBuffer ); return hr; } @@ -3868,8 +3873,10 @@ static HRESULT WINAPI DirectPlay3AImpl_EnumConnections if( !lpEnumCallback( &serviceProviderGUID, lpAddressBuffer, dwAddressBufferSize, &dpName, DPCONNECTION_DIRECTPLAYLOBBY, lpContext ) ) { + HeapFree( GetProcessHeap(), 0, lpAddressBuffer ); return DP_OK; } + HeapFree( GetProcessHeap(), 0, lpAddressBuffer ); } } diff --git a/dlls/dplayx/name_server.c b/dlls/dplayx/name_server.c index e875c19063a..1fdfef63f0c 100644 --- a/dlls/dplayx/name_server.c +++ b/dlls/dplayx/name_server.c @@ -136,6 +136,7 @@ void NS_AddRemoteComputerAsNameServer( LPCVOID lpcNSAddrHdr if( lpCacheNode->data == NULL ) { ERR( "no memory for SESSIONDESC2\n" ); + HeapFree( GetProcessHeap(), 0, lpCacheNode ); return; } diff --git a/dlls/gdi32/clipping.c b/dlls/gdi32/clipping.c index 8b019c62023..2c53dfba572 100644 --- a/dlls/gdi32/clipping.c +++ b/dlls/gdi32/clipping.c @@ -172,7 +172,7 @@ INT16 WINAPI SelectVisRgn16( HDC16 hdc16, HRGN16 hrgn ) DC * dc; if (!hrgn) return ERROR; - if (!(dc = DC_GetDCPtr( hdc ))) return ERROR; + if (!(dc = get_dc_ptr( hdc ))) return ERROR; TRACE("%p %04x\n", hdc, hrgn ); @@ -180,7 +180,7 @@ INT16 WINAPI SelectVisRgn16( HDC16 hdc16, HRGN16 hrgn ) retval = CombineRgn( dc->hVisRgn, HRGN_32(hrgn), 0, RGN_COPY ); CLIPPING_UpdateGCRegion( dc ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return retval; } @@ -478,14 +478,14 @@ INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn ) { INT ret = -1; DC * dc; - if (hRgn && (dc = DC_GetDCPtr( hdc ))) + if (hRgn && (dc = get_dc_ptr( hdc ))) { if( dc->hClipRgn ) { if( CombineRgn(hRgn, dc->hClipRgn, 0, RGN_COPY) != ERROR ) ret = 1; } else ret = 0; - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); } return ret; } @@ -497,13 +497,13 @@ INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn ) INT WINAPI GetMetaRgn( HDC hdc, HRGN hRgn ) { INT ret = 0; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (dc) { if (dc->hMetaRgn && CombineRgn( hRgn, dc->hMetaRgn, 0, RGN_COPY ) != ERROR) ret = 1; - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); } return ret; } @@ -544,7 +544,7 @@ INT16 WINAPI RestoreVisRgn16( HDC16 hdc16 ) { struct saved_visrgn *saved; HDC hdc = HDC_32( hdc16 ); - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); INT16 ret = ERROR; if (!dc) return ERROR; @@ -559,7 +559,7 @@ INT16 WINAPI RestoreVisRgn16( HDC16 hdc16 ) HeapFree( GetProcessHeap(), 0, saved ); CLIPPING_UpdateGCRegion( dc ); done: - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -628,7 +628,7 @@ INT WINAPI SetMetaRgn( HDC hdc ) { INT ret; RECT dummy; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if (!dc) return ERROR; @@ -651,6 +651,6 @@ INT WINAPI SetMetaRgn( HDC hdc ) /* Note: no need to call CLIPPING_UpdateGCRegion, the overall clip region hasn't changed */ ret = GetRgnBox( dc->hMetaRgn, &dummy ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index 465adc1441e..8dc14fe7977 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -497,7 +497,6 @@ INT WINAPI GDI_CallExtDeviceMode16( HWND hwnd, HDC hdc; DC *dc; INT ret = -1; - INT (*pExtDeviceMode)(LPSTR,HWND,LPDEVMODEA,LPSTR,LPSTR,LPDEVMODEA,LPSTR,DWORD); TRACE("(%p, %p, %s, %s, %p, %s, %d)\n", hwnd, lpdmOutput, lpszDevice, lpszPort, lpdmInput, lpszProfile, fwMode ); @@ -511,13 +510,12 @@ INT WINAPI GDI_CallExtDeviceMode16( HWND hwnd, if (!(hdc = CreateICA( buf, lpszDevice, lpszPort, NULL ))) return -1; - if ((dc = DC_GetDCPtr( hdc ))) + if ((dc = get_dc_ptr( hdc ))) { - pExtDeviceMode = dc->funcs->pExtDeviceMode; - DC_ReleaseDCPtr( dc ); - if (pExtDeviceMode) - ret = pExtDeviceMode(buf, hwnd, lpdmOutput, lpszDevice, lpszPort, - lpdmInput, lpszProfile, fwMode); + if (dc->funcs->pExtDeviceMode) + ret = dc->funcs->pExtDeviceMode( buf, hwnd, lpdmOutput, lpszDevice, lpszPort, + lpdmInput, lpszProfile, fwMode ); + release_dc_ptr( dc ); } DeleteDC( hdc ); return ret; @@ -566,12 +564,12 @@ DWORD WINAPI GDI_CallDeviceCapabilities16( LPCSTR lpszDevice, LPCSTR lpszPort, if (!(hdc = CreateICA( buf, lpszDevice, lpszPort, NULL ))) return -1; - if ((dc = DC_GetDCPtr( hdc ))) + if ((dc = get_dc_ptr( hdc ))) { if (dc->funcs->pDeviceCapabilities) ret = dc->funcs->pDeviceCapabilities( buf, lpszDevice, lpszPort, fwCapability, lpszOutput, lpdm ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); } DeleteDC( hdc ); return ret; @@ -695,12 +693,12 @@ INT WINAPI ExtEscape( HDC hdc, INT nEscape, INT cbInput, LPCSTR lpszInData, INT cbOutput, LPSTR lpszOutData ) { INT ret = 0; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (dc) { if (dc->funcs->pExtEscape) ret = dc->funcs->pExtEscape( dc->physDev, nEscape, cbInput, lpszInData, cbOutput, lpszOutData ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); } return ret; } diff --git a/dlls/gdi32/mapping.c b/dlls/gdi32/mapping.c index eccd8c992bd..234f695c80c 100644 --- a/dlls/gdi32/mapping.c +++ b/dlls/gdi32/mapping.c @@ -62,7 +62,7 @@ static void MAPPING_FixIsotropic( DC * dc ) */ BOOL16 WINAPI DPtoLP16( HDC16 hdc, LPPOINT16 points, INT16 count ) { - DC * dc = DC_GetDCPtr( HDC_32(hdc) ); + DC * dc = get_dc_ptr( HDC_32(hdc) ); if (!dc) return FALSE; while (count--) @@ -71,7 +71,7 @@ BOOL16 WINAPI DPtoLP16( HDC16 hdc, LPPOINT16 points, INT16 count ) points->y = MulDiv( points->y - dc->vportOrgY, dc->wndExtY, dc->vportExtY ) + dc->wndOrgY; points++; } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return TRUE; } @@ -81,7 +81,7 @@ BOOL16 WINAPI DPtoLP16( HDC16 hdc, LPPOINT16 points, INT16 count ) */ BOOL WINAPI DPtoLP( HDC hdc, LPPOINT points, INT count ) { - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->vport2WorldValid) @@ -99,7 +99,7 @@ BOOL WINAPI DPtoLP( HDC hdc, LPPOINT points, INT count ) points++; } } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return (count < 0); } @@ -109,7 +109,7 @@ BOOL WINAPI DPtoLP( HDC hdc, LPPOINT points, INT count ) */ BOOL16 WINAPI LPtoDP16( HDC16 hdc, LPPOINT16 points, INT16 count ) { - DC * dc = DC_GetDCPtr( HDC_32(hdc) ); + DC * dc = get_dc_ptr( HDC_32(hdc) ); if (!dc) return FALSE; while (count--) @@ -118,7 +118,7 @@ BOOL16 WINAPI LPtoDP16( HDC16 hdc, LPPOINT16 points, INT16 count ) points->y = MulDiv( points->y - dc->wndOrgY, dc->vportExtY, dc->wndExtY ) + dc->vportOrgY; points++; } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return TRUE; } @@ -128,7 +128,7 @@ BOOL16 WINAPI LPtoDP16( HDC16 hdc, LPPOINT16 points, INT16 count ) */ BOOL WINAPI LPtoDP( HDC hdc, LPPOINT points, INT count ) { - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; while (count--) @@ -143,7 +143,7 @@ BOOL WINAPI LPtoDP( HDC hdc, LPPOINT points, INT count ) dc->xformWorld2Vport.eDy + 0.5 ); points++; } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return TRUE; } @@ -156,7 +156,7 @@ INT WINAPI SetMapMode( HDC hdc, INT mode ) INT ret; INT horzSize, vertSize, horzRes, vertRes; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return 0; if (dc->funcs->pSetMapMode) { @@ -226,7 +226,7 @@ INT WINAPI SetMapMode( HDC hdc, INT mode ) dc->MapMode = mode; DC_UpdateXforms( dc ); done: - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -237,7 +237,7 @@ INT WINAPI SetMapMode( HDC hdc, INT mode ) BOOL WINAPI SetViewportExtEx( HDC hdc, INT x, INT y, LPSIZE size ) { INT ret = TRUE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->funcs->pSetViewportExt) { @@ -265,7 +265,7 @@ BOOL WINAPI SetViewportExtEx( HDC hdc, INT x, INT y, LPSIZE size ) if (dc->MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc ); DC_UpdateXforms( dc ); done: - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -276,7 +276,7 @@ BOOL WINAPI SetViewportExtEx( HDC hdc, INT x, INT y, LPSIZE size ) BOOL WINAPI SetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt ) { INT ret = TRUE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->funcs->pSetViewportOrg) { @@ -297,7 +297,7 @@ BOOL WINAPI SetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt ) DC_UpdateXforms( dc ); done: - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -308,7 +308,7 @@ BOOL WINAPI SetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt ) BOOL WINAPI SetWindowExtEx( HDC hdc, INT x, INT y, LPSIZE size ) { INT ret = TRUE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->funcs->pSetWindowExt) { @@ -339,7 +339,7 @@ BOOL WINAPI SetWindowExtEx( HDC hdc, INT x, INT y, LPSIZE size ) if (dc->MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc ); DC_UpdateXforms( dc ); done: - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -350,7 +350,7 @@ BOOL WINAPI SetWindowExtEx( HDC hdc, INT x, INT y, LPSIZE size ) BOOL WINAPI SetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt ) { INT ret = TRUE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->funcs->pSetWindowOrg) { @@ -370,7 +370,7 @@ BOOL WINAPI SetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt ) dc->wndOrgY = y; DC_UpdateXforms( dc ); done: - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -381,7 +381,7 @@ BOOL WINAPI SetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt ) BOOL WINAPI OffsetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt) { INT ret = TRUE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->funcs->pOffsetViewportOrg) { @@ -401,7 +401,7 @@ BOOL WINAPI OffsetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt) dc->vportOrgY += y; DC_UpdateXforms( dc ); done: - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -412,7 +412,7 @@ BOOL WINAPI OffsetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt) BOOL WINAPI OffsetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt ) { INT ret = TRUE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->funcs->pOffsetWindowOrg) { @@ -432,7 +432,7 @@ BOOL WINAPI OffsetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt ) dc->wndOrgY += y; DC_UpdateXforms( dc ); done: - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -444,7 +444,7 @@ BOOL WINAPI ScaleViewportExtEx( HDC hdc, INT xNum, INT xDenom, INT yNum, INT yDenom, LPSIZE size ) { INT ret = TRUE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->funcs->pScaleViewportExt) { @@ -474,7 +474,7 @@ BOOL WINAPI ScaleViewportExtEx( HDC hdc, INT xNum, INT xDenom, if (dc->MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc ); DC_UpdateXforms( dc ); done: - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -486,7 +486,7 @@ BOOL WINAPI ScaleWindowExtEx( HDC hdc, INT xNum, INT xDenom, INT yNum, INT yDenom, LPSIZE size ) { INT ret = TRUE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if (!dc) return FALSE; if (dc->funcs->pScaleWindowExt) { @@ -516,6 +516,6 @@ BOOL WINAPI ScaleWindowExtEx( HDC hdc, INT xNum, INT xDenom, if (dc->MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc ); DC_UpdateXforms( dc ); done: - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } diff --git a/dlls/gdi32/opengl.c b/dlls/gdi32/opengl.c index 164f2798afb..aebf17ada83 100644 --- a/dlls/gdi32/opengl.c +++ b/dlls/gdi32/opengl.c @@ -47,7 +47,7 @@ typedef struct opengl_context /* We route all wgl functions from opengl32.dll through gdi32.dll to * the display driver. Various wgl calls have a hDC as one of their parameters. - * Using DC_GetDCPtr we get access to the functions exported by the driver. + * Using get_dc_ptr we get access to the functions exported by the driver. * Some functions don't receive a hDC. This function creates a global hdc and * if there's already a global hdc, it returns it. */ @@ -94,13 +94,13 @@ BOOL WINAPI wglDeleteContext(HGLRC hglrc) return FALSE; /* Retrieve the HDC associated with the context to access the display driver */ - dc = DC_GetDCPtr(ctx->hdc); + dc = get_dc_ptr(ctx->hdc); if (!dc) return FALSE; if (!dc->funcs->pwglDeleteContext) FIXME(" :stub\n"); else ret = dc->funcs->pwglDeleteContext(hglrc); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -139,7 +139,7 @@ static HDC WINAPI wglGetPbufferDCARB(void *pbuffer) /* Create a device context to associate with the pbuffer */ HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL); - DC *dc = DC_GetDCPtr(hdc); + DC *dc = get_dc_ptr(hdc); TRACE("(%p)\n", pbuffer); @@ -152,8 +152,8 @@ static HDC WINAPI wglGetPbufferDCARB(void *pbuffer) else ret = dc->funcs->pwglGetPbufferDCARB(dc->physDev, pbuffer); TRACE("(%p), hdc=%p\n", pbuffer, ret); - - DC_ReleaseDCPtr( dc ); + + release_dc_ptr( dc ); return ret; } @@ -227,15 +227,15 @@ BOOL WINAPI wglShareLists(HGLRC hglrc1, HGLRC hglrc2) TRACE("hglrc1: (%p); hglrc: (%p)\n", hglrc1, hglrc2); if(ctx == NULL) return FALSE; - + /* Retrieve the HDC associated with the context to access the display driver */ - dc = DC_GetDCPtr(ctx->hdc); + dc = get_dc_ptr(ctx->hdc); if (!dc) return FALSE; if (!dc->funcs->pwglShareLists) FIXME(" :stub\n"); else ret = dc->funcs->pwglShareLists(hglrc1, hglrc2); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -245,7 +245,7 @@ BOOL WINAPI wglShareLists(HGLRC hglrc1, HGLRC hglrc2) BOOL WINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase) { BOOL ret = FALSE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); TRACE("(%p, %d, %d, %d)\n", hdc, first, count, listBase); @@ -254,7 +254,7 @@ BOOL WINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase if (!dc->funcs->pwglUseFontBitmapsA) FIXME(" :stub\n"); else ret = dc->funcs->pwglUseFontBitmapsA(dc->physDev, first, count, listBase); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -264,7 +264,7 @@ BOOL WINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase BOOL WINAPI wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase) { BOOL ret = FALSE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); TRACE("(%p, %d, %d, %d)\n", hdc, first, count, listBase); @@ -273,7 +273,7 @@ BOOL WINAPI wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase if (!dc->funcs->pwglUseFontBitmapsW) FIXME(" :stub\n"); else ret = dc->funcs->pwglUseFontBitmapsW(dc->physDev, first, count, listBase); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } diff --git a/dlls/gdi32/painting.c b/dlls/gdi32/painting.c index 1b8d6aae7cc..77d05c2022c 100644 --- a/dlls/gdi32/painting.c +++ b/dlls/gdi32/painting.c @@ -67,7 +67,7 @@ BOOL WINAPI LineTo( HDC hdc, INT x, INT y ) BOOL WINAPI MoveToEx( HDC hdc, INT x, INT y, LPPOINT pt ) { BOOL ret = TRUE; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); if(!dc) return FALSE; @@ -80,7 +80,7 @@ BOOL WINAPI MoveToEx( HDC hdc, INT x, INT y, LPPOINT pt ) if(PATH_IsPathOpen(dc->path)) ret = PATH_MoveTo(dc); else if (dc->funcs->pMoveTo) ret = dc->funcs->pMoveTo(dc->physDev,x,y); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -335,7 +335,7 @@ COLORREF WINAPI GetPixel( HDC hdc, INT x, INT y ) INT WINAPI ChoosePixelFormat( HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd ) { INT ret = 0; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); TRACE("(%p,%p)\n",hdc,ppfd); @@ -344,7 +344,7 @@ INT WINAPI ChoosePixelFormat( HDC hdc, const PIXELFORMATDESCRIPTOR* ppfd ) if (!dc->funcs->pChoosePixelFormat) FIXME(" :stub\n"); else ret = dc->funcs->pChoosePixelFormat(dc->physDev,ppfd); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -427,7 +427,7 @@ INT WINAPI DescribePixelFormat( HDC hdc, INT iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd ) { INT ret = 0; - DC * dc = DC_GetDCPtr( hdc ); + DC * dc = get_dc_ptr( hdc ); TRACE("(%p,%d,%d,%p): stub\n",hdc,iPixelFormat,nBytes,ppfd); @@ -442,7 +442,7 @@ INT WINAPI DescribePixelFormat( HDC hdc, INT iPixelFormat, UINT nBytes, } else ret = dc->funcs->pDescribePixelFormat(dc->physDev,iPixelFormat,nBytes,ppfd); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -970,7 +970,7 @@ BOOL WINAPI PolyDraw(HDC hdc, const POINT *lppt, const BYTE *lpbTypes, Polyline(hdc, line_pts, num_pts); MoveToEx(hdc, line_pts[num_pts - 1].x, line_pts[num_pts - 1].y, NULL); - + HeapFree(GetProcessHeap(), 0, line_pts); result = TRUE; } diff --git a/dlls/gdi32/path.c b/dlls/gdi32/path.c index b887a8681bf..683bdba0a2e 100644 --- a/dlls/gdi32/path.c +++ b/dlls/gdi32/path.c @@ -129,7 +129,7 @@ static inline void INTERNAL_LPTODP_FLOAT(DC *dc, FLOAT_POINT *point) BOOL WINAPI BeginPath(HDC hdc) { BOOL ret = TRUE; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if(!dc) return FALSE; @@ -148,7 +148,7 @@ BOOL WINAPI BeginPath(HDC hdc) dc->path.state=PATH_Open; } } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -159,7 +159,7 @@ BOOL WINAPI BeginPath(HDC hdc) BOOL WINAPI EndPath(HDC hdc) { BOOL ret = TRUE; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if(!dc) return FALSE; @@ -176,7 +176,7 @@ BOOL WINAPI EndPath(HDC hdc) /* Set flag to indicate that path is finished */ else dc->path.state=PATH_Closed; } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -198,7 +198,7 @@ BOOL WINAPI EndPath(HDC hdc) BOOL WINAPI AbortPath( HDC hdc ) { BOOL ret = TRUE; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if(!dc) return FALSE; @@ -206,7 +206,7 @@ BOOL WINAPI AbortPath( HDC hdc ) ret = dc->funcs->pAbortPath(dc->physDev); else /* Remove all entries from the path */ PATH_EmptyPath( &dc->path ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -219,7 +219,7 @@ BOOL WINAPI AbortPath( HDC hdc ) BOOL WINAPI CloseFigure(HDC hdc) { BOOL ret = TRUE; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if(!dc) return FALSE; @@ -245,7 +245,7 @@ BOOL WINAPI CloseFigure(HDC hdc) } } } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -258,7 +258,7 @@ INT WINAPI GetPath(HDC hdc, LPPOINT pPoints, LPBYTE pTypes, { INT ret = -1; GdiPath *pPath; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if(!dc) return -1; @@ -293,7 +293,7 @@ INT WINAPI GetPath(HDC hdc, LPPOINT pPoints, LPBYTE pTypes, else ret = pPath->numEntriesUsed; } done: - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -311,7 +311,7 @@ HRGN WINAPI PathToRegion(HDC hdc) { GdiPath *pPath; HRGN hrgnRval = 0; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); /* Get pointer to path */ if(!dc) return 0; @@ -328,7 +328,7 @@ HRGN WINAPI PathToRegion(HDC hdc) else hrgnRval=0; } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return hrgnRval; } @@ -414,7 +414,7 @@ static BOOL PATH_FillPath(DC *dc, GdiPath *pPath) */ BOOL WINAPI FillPath(HDC hdc) { - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); BOOL bRet = FALSE; if(!dc) return FALSE; @@ -431,7 +431,7 @@ BOOL WINAPI FillPath(HDC hdc) PATH_EmptyPath(&dc->path); } } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return bRet; } @@ -446,7 +446,7 @@ BOOL WINAPI SelectClipPath(HDC hdc, INT iMode) GdiPath *pPath; HRGN hrgnPath; BOOL success = FALSE; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if(!dc) return FALSE; @@ -471,7 +471,7 @@ BOOL WINAPI SelectClipPath(HDC hdc, INT iMode) /* FIXME: Should this function delete the path even if it failed? */ } } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return success; } @@ -1698,7 +1698,7 @@ static void PATH_NormalizePoint(FLOAT_POINT corners[], BOOL WINAPI FlattenPath(HDC hdc) { BOOL ret = FALSE; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if(!dc) return FALSE; @@ -1709,7 +1709,7 @@ BOOL WINAPI FlattenPath(HDC hdc) if(pPath->state != PATH_Closed) ret = PATH_FlattenPath(pPath); } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -2191,7 +2191,7 @@ static BOOL PATH_WidenPath(DC *dc) */ BOOL WINAPI StrokeAndFillPath(HDC hdc) { - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); BOOL bRet = FALSE; if(!dc) return FALSE; @@ -2204,7 +2204,7 @@ BOOL WINAPI StrokeAndFillPath(HDC hdc) if(bRet) bRet = PATH_StrokePath(dc, &dc->path); if(bRet) PATH_EmptyPath(&dc->path); } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return bRet; } @@ -2216,7 +2216,7 @@ BOOL WINAPI StrokeAndFillPath(HDC hdc) */ BOOL WINAPI StrokePath(HDC hdc) { - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); GdiPath *pPath; BOOL bRet = FALSE; @@ -2231,7 +2231,7 @@ BOOL WINAPI StrokePath(HDC hdc) bRet = PATH_StrokePath(dc, pPath); PATH_EmptyPath(pPath); } - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return bRet; } @@ -2243,7 +2243,7 @@ BOOL WINAPI StrokePath(HDC hdc) */ BOOL WINAPI WidenPath(HDC hdc) { - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); BOOL ret = FALSE; if(!dc) return FALSE; @@ -2252,6 +2252,6 @@ BOOL WINAPI WidenPath(HDC hdc) ret = dc->funcs->pWidenPath(dc->physDev); else ret = PATH_WidenPath(dc); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } diff --git a/dlls/gdi32/printdrv.c b/dlls/gdi32/printdrv.c index 944453685ea..bdd754f6726 100644 --- a/dlls/gdi32/printdrv.c +++ b/dlls/gdi32/printdrv.c @@ -71,7 +71,7 @@ static const char Printers[] = "System\\CurrentControlSet\\Control\\Pri INT WINAPI StartDocW(HDC hdc, const DOCINFOW* doc) { INT ret = 0; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); TRACE("DocName = %s Output = %s Datatype = %s\n", debugstr_w(doc->lpszDocName), debugstr_w(doc->lpszOutput), @@ -80,7 +80,7 @@ INT WINAPI StartDocW(HDC hdc, const DOCINFOW* doc) if(!dc) return SP_ERROR; if (dc->funcs->pStartDoc) ret = dc->funcs->pStartDoc( dc->physDev, doc ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -136,11 +136,11 @@ INT WINAPI StartDocA(HDC hdc, const DOCINFOA* doc) INT WINAPI EndDoc(HDC hdc) { INT ret = 0; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if(!dc) return SP_ERROR; if (dc->funcs->pEndDoc) ret = dc->funcs->pEndDoc( dc->physDev ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -152,14 +152,14 @@ INT WINAPI EndDoc(HDC hdc) INT WINAPI StartPage(HDC hdc) { INT ret = 1; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if(!dc) return SP_ERROR; if(dc->funcs->pStartPage) ret = dc->funcs->pStartPage( dc->physDev ); else FIXME("stub\n"); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -170,19 +170,17 @@ INT WINAPI StartPage(HDC hdc) */ INT WINAPI EndPage(HDC hdc) { - ABORTPROC abort_proc; INT ret = 0; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if(!dc) return SP_ERROR; if (dc->funcs->pEndPage) ret = dc->funcs->pEndPage( dc->physDev ); - abort_proc = dc->pAbortProc; - DC_ReleaseDCPtr( dc ); - if (abort_proc && !abort_proc( hdc, 0 )) + if (dc->pAbortProc && !dc->pAbortProc( hdc, 0 )) { EndDoc( hdc ); ret = 0; } + release_dc_ptr( dc ); return ret; } @@ -193,11 +191,11 @@ INT WINAPI EndPage(HDC hdc) INT WINAPI AbortDoc(HDC hdc) { INT ret = 0; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if(!dc) return SP_ERROR; if (dc->funcs->pAbortDoc) ret = dc->funcs->pAbortDoc( dc->physDev ); - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return ret; } @@ -214,19 +212,14 @@ BOOL16 WINAPI QueryAbort16(HDC16 hdc16, INT16 reserved) { BOOL ret = TRUE; HDC hdc = HDC_32( hdc16 ); - DC *dc = DC_GetDCPtr( hdc ); - ABORTPROC abproc; + DC *dc = get_dc_ptr( hdc ); if(!dc) { ERR("Invalid hdc %p\n", hdc); return FALSE; } - - abproc = dc->pAbortProc; - DC_ReleaseDCPtr( dc ); - - if (abproc) - ret = abproc(hdc, 0); + if (dc->pAbortProc) ret = dc->pAbortProc(hdc, 0); + release_dc_ptr( dc ); return ret; } @@ -237,11 +230,11 @@ BOOL16 WINAPI QueryAbort16(HDC16 hdc16, INT16 reserved) static BOOL CALLBACK call_abort_proc16( HDC hdc, INT code ) { ABORTPROC16 proc16; - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if (!dc) return FALSE; proc16 = dc->pAbortProc16; - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); if (proc16) { WORD args[2]; @@ -262,12 +255,13 @@ static BOOL CALLBACK call_abort_proc16( HDC hdc, INT code ) INT16 WINAPI SetAbortProc16(HDC16 hdc16, ABORTPROC16 abrtprc) { HDC hdc = HDC_32( hdc16 ); - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if (!dc) return FALSE; dc->pAbortProc16 = abrtprc; - DC_ReleaseDCPtr( dc ); - return SetAbortProc( hdc, call_abort_proc16 ); + dc->pAbortProc = call_abort_proc16; + release_dc_ptr( dc ); + return TRUE; } /********************************************************************** @@ -276,11 +270,11 @@ INT16 WINAPI SetAbortProc16(HDC16 hdc16, ABORTPROC16 abrtprc) */ INT WINAPI SetAbortProc(HDC hdc, ABORTPROC abrtprc) { - DC *dc = DC_GetDCPtr( hdc ); + DC *dc = get_dc_ptr( hdc ); if (!dc) return FALSE; dc->pAbortProc = abrtprc; - DC_ReleaseDCPtr( dc ); + release_dc_ptr( dc ); return TRUE; } diff --git a/dlls/itss/protocol.c b/dlls/itss/protocol.c index dd30c7de8d1..d7f3f4252f2 100644 --- a/dlls/itss/protocol.c +++ b/dlls/itss/protocol.c @@ -216,7 +216,7 @@ static HRESULT WINAPI ITSProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, res = chm_resolve_object(chm_file, object_name, &chm_object); if(res != CHM_RESOLVE_SUCCESS) { WARN("Could not resolve chm object\n"); - HeapFree(GetProcessHeap(), 0, object_name); + HeapFree(GetProcessHeap(), 0, file_name); chm_close(chm_file); return report_result(pOIProtSink, STG_E_FILENOTFOUND); } diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c index 78c56436d04..49706281e94 100644 --- a/dlls/kernel32/tests/virtual.c +++ b/dlls/kernel32/tests/virtual.c @@ -271,6 +271,7 @@ static void test_MapViewOfFile(void) static const char testfile[] = "testfile.xxx"; HANDLE file, mapping; void *ptr; + MEMORY_BASIC_INFORMATION info; SetLastError(0xdeadbeef); file = CreateFileA( testfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); @@ -457,6 +458,41 @@ static void test_MapViewOfFile(void) ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 ); todo_wine ok( !ptr, "MapViewOfFile FILE_MAP_WRITE should fail\n" ); todo_wine ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() ); + SetLastError(0xdeadbeef); + ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); + ok( ptr != NULL, "MapViewOfFile FILE_MAP_READ error %u\n", GetLastError() ); + SetLastError(0xdeadbeef); + ok( VirtualQuery( ptr, &info, sizeof(info) ) == sizeof(info), + "VirtualQuery error %u\n", GetLastError() ); + ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr ); + ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr ); +todo_wine ok( info.AllocationProtect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.AllocationProtect ); + ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize ); + ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State ); +todo_wine ok( info.Protect == PAGE_READONLY, "%x != PAGE_READONLY\n", info.Protect ); + UnmapViewOfFile( ptr ); + CloseHandle( mapping ); + + SetLastError(0xdeadbeef); + mapping = OpenFileMapping( FILE_MAP_WRITE, FALSE, "Global\\Foo" ); + ok( mapping != 0, "OpenFileMapping FILE_MAP_WRITE error %u\n", GetLastError() ); + SetLastError(0xdeadbeef); + ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); +todo_wine ok( !ptr, "MapViewOfFile FILE_MAP_READ should fail\n" ); +todo_wine ok( GetLastError() == ERROR_ACCESS_DENIED, "Wrong error %d\n", GetLastError() ); + SetLastError(0xdeadbeef); + ptr = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 ); + ok( ptr != NULL, "MapViewOfFile FILE_MAP_WRITE error %u\n", GetLastError() ); + SetLastError(0xdeadbeef); + ok( VirtualQuery( ptr, &info, sizeof(info) ) == sizeof(info), + "VirtualQuery error %u\n", GetLastError() ); + ok( info.BaseAddress == ptr, "%p != %p\n", info.BaseAddress, ptr ); + ok( info.AllocationBase == ptr, "%p != %p\n", info.AllocationBase, ptr ); + ok( info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect ); + ok( info.RegionSize == 4096, "%lx != 4096\n", info.RegionSize ); + ok( info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State ); + ok( info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect ); + UnmapViewOfFile( ptr ); CloseHandle( mapping ); CloseHandle( file ); diff --git a/dlls/mpr/pwcache.c b/dlls/mpr/pwcache.c index f8d3e322041..a760dd26d25 100644 --- a/dlls/mpr/pwcache.c +++ b/dlls/mpr/pwcache.c @@ -56,8 +56,9 @@ static LPSTR MPR_GetValueName( LPCSTR pbResource, WORD cbResource, BYTE nType ) DWORD i; name = HeapAlloc( GetProcessHeap(), 0, 6+cbResource*2 ); - if( name ) - sprintf( name, "X-%02X-", nType ); + if( !name ) return NULL; + + sprintf( name, "X-%02X-", nType ); for(i=0; i>4); diff --git a/dlls/mshtml/htmlbody.c b/dlls/mshtml/htmlbody.c index b8c153a76b8..30643478b42 100644 --- a/dlls/mshtml/htmlbody.c +++ b/dlls/mshtml/htmlbody.c @@ -40,8 +40,6 @@ typedef struct { const IHTMLBodyElementVtbl *lpHTMLBodyElementVtbl; - HTMLTextContainer text_container; - ConnectionPointContainer cp_container; ConnectionPoint cp_propnotif; ConnectionPoint cp_txtcontevents; @@ -71,8 +69,8 @@ static HRESULT WINAPI HTMLBodyElement_QueryInterface(IHTMLBodyElement *iface, TRACE("(%p)->(IID_IHTMLBodyElement %p)\n", This, ppv); *ppv = HTMLBODY(This); }else if(IsEqualGUID(&IID_IHTMLTextContainer, riid)) { - TRACE("(%p)->(IID_IHTMLTextContainer %p)\n", This, ppv); - *ppv = HTMLTEXTCONT(&This->text_container); + TRACE("(%p)->(IID_IHTMLTextContainer %p)\n", &This->textcont, ppv); + *ppv = HTMLTEXTCONT(&This->textcont); }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) { TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv); *ppv = CONPTCONT(&This->cp_container); @@ -487,9 +485,11 @@ HTMLElement *HTMLBodyElement_Create(nsIDOMHTMLElement *nselem) HTMLBodyElement *ret = mshtml_alloc(sizeof(HTMLBodyElement)); nsresult nsres; + TRACE("(%p)->(%p)\n", ret, nselem); + ret->lpHTMLBodyElementVtbl = &HTMLBodyElementVtbl; - HTMLTextContainer_Init(&ret->text_container); + HTMLTextContainer_Init(&ret->textcont); ConnectionPoint_Init(&ret->cp_propnotif, CONPTCONT(&ret->cp_container), &IID_IPropertyNotifySink, NULL); diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c index 05071d86cf6..77d50b0c85a 100644 --- a/dlls/mshtml/htmlelem.c +++ b/dlls/mshtml/htmlelem.c @@ -1291,7 +1291,7 @@ HTMLElement *HTMLElement_Create(nsIDOMNode *nsnode) ret = HTMLBodyElement_Create(nselem); else if(!strcmpW(class_name, wszINPUT)) ret = HTMLInputElement_Create(nselem); - if(!strcmpW(class_name, wszSELECT)) + else if(!strcmpW(class_name, wszSELECT)) ret = HTMLSelectElement_Create(nselem); else if(!strcmpW(class_name, wszTEXTAREA)) ret = HTMLTextAreaElement_Create(nselem); diff --git a/dlls/mshtml/view.c b/dlls/mshtml/view.c index a201de03172..e5ef7a7419a 100644 --- a/dlls/mshtml/view.c +++ b/dlls/mshtml/view.c @@ -577,7 +577,8 @@ static HRESULT WINAPI OleDocumentView_UIActivate(IOleDocumentView *iface, BOOL f } This->focus = TRUE; - nsIWebBrowserFocus_Activate(This->nscontainer->focus); + if(This->nscontainer) + nsIWebBrowserFocus_Activate(This->nscontainer->focus); notif_focus(This); update_doc(This, UPDATE_UI); diff --git a/dlls/msvcrt/dir.c b/dlls/msvcrt/dir.c index 06013c69852..3da6efaa69c 100644 --- a/dlls/msvcrt/dir.c +++ b/dlls/msvcrt/dir.c @@ -1010,3 +1010,66 @@ void CDECL _searchenv(const char* file, const char* env, char *buf) penv = *end ? end + 1 : end; } while(1); } + +/********************************************************************* + * _wsearchenv (MSVCRT.@) + * + * Unicode version of _searchenv + */ +void CDECL _wsearchenv(const MSVCRT_wchar_t* file, const MSVCRT_wchar_t* env, MSVCRT_wchar_t *buf) +{ + MSVCRT_wchar_t *envVal, *penv; + MSVCRT_wchar_t curPath[MAX_PATH]; + + *buf = '\0'; + + /* Try CWD first */ + if (GetFileAttributesW( file ) != INVALID_FILE_ATTRIBUTES) + { + GetFullPathNameW( file, MAX_PATH, buf, NULL ); + /* Sigh. This error is *always* set, regardless of success */ + msvcrt_set_errno(ERROR_FILE_NOT_FOUND); + return; + } + + /* Search given environment variable */ + envVal = _wgetenv(env); + if (!envVal) + { + msvcrt_set_errno(ERROR_FILE_NOT_FOUND); + return; + } + + penv = envVal; + TRACE(":searching for %s in paths %s\n", debugstr_w(file), debugstr_w(envVal)); + + do + { + MSVCRT_wchar_t *end = penv; + + while(*end && *end != ';') end++; /* Find end of next path */ + if (penv == end || !*penv) + { + msvcrt_set_errno(ERROR_FILE_NOT_FOUND); + return; + } + memcpy(curPath, penv, (end - penv) * sizeof(MSVCRT_wchar_t)); + if (curPath[end - penv] != '/' || curPath[end - penv] != '\\') + { + curPath[end - penv] = '\\'; + curPath[end - penv + 1] = '\0'; + } + else + curPath[end - penv] = '\0'; + + strcatW(curPath, file); + TRACE("Checking for file %s\n", debugstr_w(curPath)); + if (GetFileAttributesW( curPath ) != INVALID_FILE_ATTRIBUTES) + { + strcpyW(buf, curPath); + msvcrt_set_errno(ERROR_FILE_NOT_FOUND); + return; /* Found */ + } + penv = *end ? end + 1 : end; + } while(1); +} diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index c46b5c47700..4ceae0beea1 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -283,23 +283,23 @@ static int msvcrt_init_fp(MSVCRT_FILE* file, int fd, unsigned stream_flags) * 04 char file flags (wxflag): repeated for each fd * 4+NBFD HANDLE file handle: repeated for each fd */ -unsigned msvcrt_create_io_inherit_block(STARTUPINFOA* si) +unsigned msvcrt_create_io_inherit_block(WORD *size, BYTE **block) { int fd; char* wxflag_ptr; HANDLE* handle_ptr; - si->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * MSVCRT_fdend; - si->lpReserved2 = MSVCRT_calloc(si->cbReserved2, 1); - if (!si->lpReserved2) + *size = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * MSVCRT_fdend; + *block = MSVCRT_calloc(*size, 1); + if (!*block) { - si->cbReserved2 = 0; + *size = 0; return FALSE; } - wxflag_ptr = (char*)si->lpReserved2 + sizeof(unsigned); + wxflag_ptr = (char*)*block + sizeof(unsigned); handle_ptr = (HANDLE*)(wxflag_ptr + MSVCRT_fdend * sizeof(char)); - *(unsigned*)si->lpReserved2 = MSVCRT_fdend; + *(unsigned*)*block = MSVCRT_fdend; for (fd = 0; fd < MSVCRT_fdend; fd++) { /* to be inherited, we need it to be open, and that DONTINHERIT isn't set */ diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index f06166bdaab..b449af547ea 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -873,16 +873,81 @@ char * CDECL _ecvt( double number, int ndigits, int *decpt, int *sign ) char * CDECL _fcvt( double number, int ndigits, int *decpt, int *sign ) { thread_data_t *data = msvcrt_get_thread_data(); - char *dec; + int stop, dec1, dec2; + char *ptr1, *ptr2, *first; + char buf[80]; /* ought to be enough */ if (!data->efcvt_buffer) data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */ - snprintf(data->efcvt_buffer, 80, "%.*e", ndigits, number); - *sign = (number < 0); - dec = strchr(data->efcvt_buffer, '.'); - *decpt = (dec) ? dec - data->efcvt_buffer : -1; - return data->efcvt_buffer; + if (number < 0) + { + *sign = 1; + number = -number; + } else *sign = 0; + + snprintf(buf, 80, "%.*f", ndigits < 0 ? 0 : ndigits, number); + ptr1 = buf; + ptr2 = data->efcvt_buffer; + first = NULL; + dec1 = 0; + dec2 = 0; + + /* For numbers below the requested resolution, work out where + the decimal point will be rather than finding it in the string */ + if (number < 1.0 && number > 0.0) { + dec2 = log10(number + 1e-10); + if (-dec2 <= ndigits) dec2 = 0; + } + + /* If requested digits is zero or less, we will need to truncate + * the returned string */ + if (ndigits < 1) { + stop = strlen(buf) + ndigits; + } else { + stop = strlen(buf); + } + + while (*ptr1 == '0') ptr1++; /* Skip leading zeroes */ + while (*ptr1 != '\0' && *ptr1 != '.') { + if (!first) first = ptr2; + if ((ptr1 - buf) < stop) { + *ptr2++ = *ptr1++; + } else { + ptr1++; + } + dec1++; + } + + if (ndigits > 0) { + ptr1++; + if (!first) { + while (*ptr1 == '0') { /* Process leading zeroes */ + *ptr2++ = *ptr1++; + dec1--; + } + } + while (*ptr1 != '\0') { + if (!first) first = ptr2; + *ptr2++ = *ptr1++; + } + } + + *ptr2 = '\0'; + + /* We never found a non-zero digit, then our number is either + * smaller than the requested precision, or 0.0 */ + if (!first) { + if (number > 0.0) { + first = ptr2; + } else { + first = data->efcvt_buffer; + dec1 = 0; + } + } + + *decpt = dec2 ? dec2 : dec1; + return first; } /*********************************************************************** diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 3a9d5c3bfba..204fe9ca55e 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -152,7 +152,7 @@ extern void msvcrt_free_args(void); extern void msvcrt_init_signals(void); extern void msvcrt_free_signals(void); -extern unsigned msvcrt_create_io_inherit_block(STARTUPINFOA*); +extern unsigned msvcrt_create_io_inherit_block(WORD*, BYTE**); /* run-time error codes */ #define _RT_STACK 0 @@ -651,6 +651,8 @@ int MSVCRT__close(int); int MSVCRT__dup(int); int MSVCRT__dup2(int, int); int MSVCRT__pipe(int *, unsigned int, int); +MSVCRT_wchar_t* _wgetenv(const MSVCRT_wchar_t*); +void _wsearchenv(const MSVCRT_wchar_t*, const MSVCRT_wchar_t*, MSVCRT_wchar_t*); #endif #endif /* __WINE_MSVCRT_H */ diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index 10a8686cfdd..5711946372d 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -552,17 +552,17 @@ @ cdecl _wrename(wstr wstr) @ cdecl _write(long ptr long) MSVCRT__write @ cdecl _wrmdir(wstr) -@ stub _wsearchenv #(wstr wstr ptr) +@ stdcall _wsearchenv(wstr wstr ptr) @ cdecl _wsetlocale(long wstr) MSVCRT__wsetlocale @ varargs _wsopen (wstr long long) MSVCRT__wsopen @ stub _wspawnl #(long wstr wstr) varargs @ stub _wspawnle #(long wstr wstr) varargs @ stub _wspawnlp #(long wstr wstr) varargs @ stub _wspawnlpe #(long wstr wstr) varargs -@ stub _wspawnv #(long wstr ptr) -@ stub _wspawnve #(long wstr ptr ptr) -@ stub _wspawnvp #(long wstr ptr) -@ stub _wspawnvpe #(long wstr ptr ptr) +@ stdcall _wspawnv(long wstr ptr) +@ stdcall _wspawnve(long wstr ptr ptr) +@ stdcall _wspawnvp(long wstr ptr) +@ stdcall _wspawnvpe(long wstr ptr ptr) @ cdecl _wsplitpath(wstr wstr wstr wstr wstr) @ cdecl _wstat(wstr ptr) MSVCRT__wstat @ cdecl _wstati64(wstr ptr) MSVCRT__wstati64 diff --git a/dlls/msvcrt/process.c b/dlls/msvcrt/process.c index c6c3a7e4609..14f8e9a28bd 100644 --- a/dlls/msvcrt/process.c +++ b/dlls/msvcrt/process.c @@ -31,6 +31,7 @@ #include "msvcrt.h" #include "wine/debug.h" +#include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); @@ -48,7 +49,7 @@ static MSVCRT_intptr_t msvcrt_spawn(int flags, const char* exe, char* cmdline, c memset(&si, 0, sizeof(si)); si.cb = sizeof(si); - msvcrt_create_io_inherit_block(&si); + msvcrt_create_io_inherit_block(&si.cbReserved2, &si.lpReserved2); if (!CreateProcessA(exe, cmdline, NULL, NULL, TRUE, flags == MSVCRT__P_DETACH ? DETACHED_PROCESS : 0, env, NULL, &si, &pi)) @@ -81,6 +82,52 @@ static MSVCRT_intptr_t msvcrt_spawn(int flags, const char* exe, char* cmdline, c return -1; /* can't reach here */ } +static MSVCRT_intptr_t msvcrt_spawn_wide(int flags, const MSVCRT_wchar_t* exe, MSVCRT_wchar_t* cmdline, MSVCRT_wchar_t* env) +{ + STARTUPINFOW si; + PROCESS_INFORMATION pi; + + if ((unsigned)flags > MSVCRT__P_DETACH) + { + *MSVCRT__errno() = MSVCRT_EINVAL; + return -1; + } + + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + msvcrt_create_io_inherit_block(&si.cbReserved2, &si.lpReserved2); + if (!CreateProcessW(exe, cmdline, NULL, NULL, TRUE, + flags == MSVCRT__P_DETACH ? DETACHED_PROCESS : 0, + env, NULL, &si, &pi)) + { + msvcrt_set_errno(GetLastError()); + MSVCRT_free(si.lpReserved2); + return -1; + } + + MSVCRT_free(si.lpReserved2); + switch(flags) + { + case MSVCRT__P_WAIT: + WaitForSingleObject(pi.hProcess, INFINITE); + GetExitCodeProcess(pi.hProcess,&pi.dwProcessId); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return pi.dwProcessId; + case MSVCRT__P_DETACH: + CloseHandle(pi.hProcess); + pi.hProcess = 0; + /* fall through */ + case MSVCRT__P_NOWAIT: + case MSVCRT__P_NOWAITO: + CloseHandle(pi.hThread); + return (MSVCRT_intptr_t)pi.hProcess; + case MSVCRT__P_OVERLAY: + MSVCRT__exit(0); + } + return -1; /* can't reach here */ +} + /* INTERNAL: Convert argv list to a single 'delim'-separated string, with an * extra '\0' to terminate it */ @@ -126,6 +173,48 @@ static char* msvcrt_argvtos(const char* const* arg, char delim) return ret; } +static MSVCRT_wchar_t* msvcrt_argvtos_wide(const MSVCRT_wchar_t* const* arg, MSVCRT_wchar_t delim) +{ + const MSVCRT_wchar_t* const* a; + long size; + MSVCRT_wchar_t* p; + MSVCRT_wchar_t* ret; + + if (!arg && !delim) + { + /* Return NULL for an empty environment list */ + return NULL; + } + + /* get length */ + a = arg; + size = 0; + while (*a) + { + size += strlenW(*a) + 1; + a++; + } + + ret = MSVCRT_malloc((size + 1) * sizeof(MSVCRT_wchar_t)); + if (!ret) + return NULL; + + /* fill string */ + a = arg; + p = ret; + while (*a) + { + int len = strlenW(*a); + memcpy(p,*a,len * sizeof(MSVCRT_wchar_t)); + p += len; + *p++ = delim; + a++; + } + if (delim && p > ret) p[-1] = 0; + else *p = 0; + return ret; +} + /* INTERNAL: Convert va_list to a single 'delim'-separated string, with an * extra '\0' to terminate it */ @@ -488,6 +577,63 @@ MSVCRT_intptr_t CDECL _spawnve(int flags, const char* name, const char* const* a } /********************************************************************* + * _wspawnve (MSVCRT.@) + * + * Unicode version of _spawnve + */ +MSVCRT_intptr_t CDECL _wspawnve(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv, + const MSVCRT_wchar_t* const* envv) +{ + MSVCRT_wchar_t * args = msvcrt_argvtos_wide(argv,' '); + MSVCRT_wchar_t * envs = msvcrt_argvtos_wide(envv,0); + MSVCRT_wchar_t fullname[MAX_PATH]; + const MSVCRT_wchar_t *p; + int len; + MSVCRT_intptr_t ret = -1; + + TRACE(":call (%s), params (%s), env (%s)\n",debugstr_w(name),debugstr_w(args), + envs?"Custom":"Null"); + + /* no check for NULL name. + native doesn't do it */ + + p = memchrW(name, '\0', MAX_PATH); + if( !p ) + p = name + MAX_PATH - 1; + len = p - name; + + /* extra-long names are silently truncated. */ + memcpy(fullname, name, len * sizeof(MSVCRT_wchar_t)); + + for( p--; p >= name; p-- ) + { + if( *p == '\\' || *p == '/' || *p == ':' || *p == '.' ) + break; + } + + /* if no extension is given, assume .exe */ + if( (p < name || *p != '.') && len <= MAX_PATH - 5 ) + { + static const MSVCRT_wchar_t dotexe[] = {'.','e','x','e'}; + + FIXME("only trying .exe when no extension given\n"); + memcpy(fullname+len, dotexe, 4 * sizeof(MSVCRT_wchar_t)); + len += 4; + } + + fullname[len] = '\0'; + + if (args) + { + ret = msvcrt_spawn_wide(flags, fullname, args, envs); + MSVCRT_free(args); + } + MSVCRT_free(envs); + + return ret; +} + +/********************************************************************* * _spawnv (MSVCRT.@) * * Like on Windows, this function does not handle arguments with spaces @@ -499,6 +645,16 @@ MSVCRT_intptr_t CDECL _spawnv(int flags, const char* name, const char* const* ar } /********************************************************************* + * _wspawnv (MSVCRT.@) + * + * Unicode version of _spawnv + */ +MSVCRT_intptr_t CDECL _wspawnv(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv) +{ + return _wspawnve(flags, name, argv, NULL); +} + +/********************************************************************* * _spawnvpe (MSVCRT.@) * * Like on Windows, this function does not handle arguments with spaces @@ -513,6 +669,21 @@ MSVCRT_intptr_t CDECL _spawnvpe(int flags, const char* name, const char* const* } /********************************************************************* + * _wspawnvpe (MSVCRT.@) + * + * Unicode version of _spawnvpe + */ +MSVCRT_intptr_t CDECL _wspawnvpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv, + const MSVCRT_wchar_t* const* envv) +{ + static const MSVCRT_wchar_t path[] = {'P','A','T','H',0}; + MSVCRT_wchar_t fullname[MAX_PATH]; + + _wsearchenv(name, path, fullname); + return _wspawnve(flags, fullname[0] ? fullname : name, argv, envv); +} + +/********************************************************************* * _spawnvp (MSVCRT.@) * * Like on Windows, this function does not handle arguments with spaces @@ -524,6 +695,16 @@ MSVCRT_intptr_t CDECL _spawnvp(int flags, const char* name, const char* const* a } /********************************************************************* + * _wspawnvp (MSVCRT.@) + * + * Unicode version of _spawnvp + */ +MSVCRT_intptr_t CDECL _wspawnvp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv) +{ + return _wspawnvpe(flags, name, argv, NULL); +} + +/********************************************************************* * _popen (MSVCRT.@) * FIXME: convert to _wpopen and call that from here instead? But it * would have to convert the command back to ANSI to call msvcrt_spawn, diff --git a/dlls/msvcrt/tests/printf.c b/dlls/msvcrt/tests/printf.c index 61672f9b526..7e07241f9b8 100644 --- a/dlls/msvcrt/tests/printf.c +++ b/dlls/msvcrt/tests/printf.c @@ -552,47 +552,96 @@ static void test_fcvt(void) char *str; int dec=100, sign=100; + /* Numbers less than 1.0 with different precisions */ str = _fcvt(0.0001, 1, &dec, &sign ); - todo_wine { - ok( 0 == strcmp(str,""), "bad return\n"); - ok( -3 == dec, "dec wrong\n"); - } - ok( 0 == sign, "dec wrong\n"); + ok( 0 == strcmp(str,""), "bad return '%s'\n", str); + ok( -3 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); str = _fcvt(0.0001, -10, &dec, &sign ); - todo_wine { - ok( 0 == strcmp(str,""), "bad return\n"); - ok( -3 == dec, "dec wrong\n"); - } - ok( 0 == sign, "dec wrong\n"); + ok( 0 == strcmp(str,""), "bad return '%s'\n", str); + ok( -3 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); str = _fcvt(0.0001, 10, &dec, &sign ); - todo_wine { - ok( 0 == strcmp(str,"1000000"), "bad return\n"); - ok( -3 == dec, "dec wrong\n"); - } - ok( 0 == sign, "dec wrong\n"); + ok( 0 == strcmp(str,"1000000"), "bad return '%s'\n", str); + ok( -3 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + /* Basic sign test */ str = _fcvt(-111.0001, 5, &dec, &sign ); - todo_wine { - ok( 0 == strcmp(str,"11100010"), "bad return\n"); - ok( 3 == dec, "dec wrong\n"); - } - ok( 1 == sign, "dec wrong\n"); + ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 1 == sign, "sign wrong\n"); str = _fcvt(111.0001, 5, &dec, &sign ); - todo_wine { - ok( 0 == strcmp(str,"11100010"), "bad return\n"); + ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str); ok( 3 == dec, "dec wrong\n"); - } - ok( 0 == sign, "dec wrong\n"); + ok( 0 == sign, "sign wrong\n"); + /* 0.0 with different precisions */ str = _fcvt(0.0, 5, &dec, &sign ); - todo_wine { - ok( 0 == strcmp(str,"00000"), "bad return\n"); - ok( 0 == dec, "dec wrong\n"); - } - ok( 0 == sign, "dec wrong\n"); + ok( 0 == strcmp(str,"00000"), "bad return '%s'\n", str); + ok( 0 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + str = _fcvt(0.0, 0, &dec, &sign ); + ok( 0 == strcmp(str,""), "bad return '%s'\n", str); + ok( 0 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + str = _fcvt(0.0, -1, &dec, &sign ); + ok( 0 == strcmp(str,""), "bad return '%s'\n", str); + ok( 0 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + /* Numbers > 1.0 with 0 or -ve precision */ + str = _fcvt(-123.0001, 0, &dec, &sign ); + ok( 0 == strcmp(str,"123"), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 1 == sign, "sign wrong\n"); + + str = _fcvt(-123.0001, -1, &dec, &sign ); + ok( 0 == strcmp(str,"12"), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 1 == sign, "sign wrong\n"); + + str = _fcvt(-123.0001, -2, &dec, &sign ); + ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 1 == sign, "sign wrong\n"); + + str = _fcvt(-123.0001, -3, &dec, &sign ); + ok( 0 == strcmp(str,""), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 1 == sign, "sign wrong\n"); + + /* Numbers > 1.0, but with rounding at the point of precision */ + str = _fcvt(99.99, 1, &dec, &sign ); + ok( 0 == strcmp(str,"1000"), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + /* Numbers < 1.0 where rounding occurs at the point of precision */ + str = _fcvt(0.00636, 2, &dec, &sign ); + ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str); + ok( -1 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + str = _fcvt(0.00636, 3, &dec, &sign ); + ok( 0 == strcmp(str,"6"), "bad return '%s'\n", str); + ok( -2 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + str = _fcvt(0.09999999996, 2, &dec, &sign ); + ok( 0 == strcmp(str,"10"), "bad return '%s'\n", str); + ok( 0 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + str = _fcvt(0.6, 0, &dec, &sign ); + ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str); + ok( 1 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); } START_TEST(printf) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 04172f90ef9..6c1d7bc2d0d 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1444,7 +1444,7 @@ static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file, } SERVER_END_REQ; - if (TRACE_ON(snoop)) SNOOP_SetupDLL( module ); + if ((wm->ldr.Flags & LDR_IMAGE_IS_DLL) && TRACE_ON(snoop)) SNOOP_SetupDLL( module ); TRACE_(loaddll)( " Loaded module %s : native\n", debugstr_w(wm->ldr.FullDllName.Buffer) ); diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 07abf1c32cd..1c4a39d8b5c 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -402,8 +402,8 @@ @ stub RtlAddActionToRXact @ stdcall RtlAddAtomToAtomTable(ptr wstr ptr) @ stub RtlAddAttributeActionToRXact -@ stdcall RtlAddAuditAccessAce(ptr long long ptr long long) -# @ stub RtlAddAuditAccessAceEx +@ stdcall RtlAddAuditAccessAce(ptr long long ptr long long) +@ stdcall RtlAddAuditAccessAceEx(ptr long long long ptr long long) # @ stub RtlAddAuditAccessObjectAce # @ stub RtlAddCompoundAce # @ stub RtlAddRange diff --git a/dlls/ntdll/sec.c b/dlls/ntdll/sec.c index af89b724ea2..0eaa9fe6a60 100644 --- a/dlls/ntdll/sec.c +++ b/dlls/ntdll/sec.c @@ -1213,17 +1213,16 @@ NTSTATUS WINAPI RtlAddAccessDeniedAceEx( /************************************************************************** * RtlAddAuditAccessAce [NTDLL.@] */ -NTSTATUS WINAPI RtlAddAuditAccessAce( +NTSTATUS WINAPI RtlAddAuditAccessAceEx( IN OUT PACL pAcl, IN DWORD dwAceRevision, + IN DWORD dwAceFlags, IN DWORD dwAccessMask, IN PSID pSid, IN BOOL bAuditSuccess, IN BOOL bAuditFailure) { - DWORD dwAceFlags = 0; - - TRACE("(%p,%d,%d,%p,%u,%u)\n",pAcl,dwAceRevision,dwAccessMask, + TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask, pSid,bAuditSuccess,bAuditFailure); if (bAuditSuccess) @@ -1235,6 +1234,20 @@ NTSTATUS WINAPI RtlAddAuditAccessAce( return add_access_ace(pAcl, dwAceRevision, dwAceFlags, dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE); } + +/************************************************************************** + * RtlAddAuditAccessAce [NTDLL.@] + */ +NTSTATUS WINAPI RtlAddAuditAccessAce( + IN OUT PACL pAcl, + IN DWORD dwAceRevision, + IN DWORD dwAccessMask, + IN PSID pSid, + IN BOOL bAuditSuccess, + IN BOOL bAuditFailure) +{ + return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure); +} /****************************************************************************** * RtlValidAcl [NTDLL.@] diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 004095b02f5..8ece976c3ce 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -1008,9 +1008,28 @@ NTSTATUS WINAPI NtDelayExecution( BOOLEAN alertable, const LARGE_INTEGER *timeou NTSTATUS WINAPI NtCreateIoCompletion( PHANDLE CompletionPort, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, ULONG NumberOfConcurrentThreads ) { - FIXME("(%p, %x, %p, %d)\n", CompletionPort, DesiredAccess, + NTSTATUS status; + + TRACE("(%p, %x, %p, %d)\n", CompletionPort, DesiredAccess, ObjectAttributes, NumberOfConcurrentThreads); - return STATUS_NOT_IMPLEMENTED; + + if (!CompletionPort) + return STATUS_INVALID_PARAMETER; + + SERVER_START_REQ( create_completion ) + { + req->access = DesiredAccess; + req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0; + req->rootdir = ObjectAttributes ? ObjectAttributes->RootDirectory : NULL; + req->concurrent = NumberOfConcurrentThreads; + if (ObjectAttributes && ObjectAttributes->ObjectName) + wine_server_add_data( req, ObjectAttributes->ObjectName->Buffer, + ObjectAttributes->ObjectName->Length ); + if (!(status = wine_server_call( req ))) + *CompletionPort = reply->handle; + } + SERVER_END_REQ; + return status; } /****************************************************************** @@ -1028,11 +1047,24 @@ NTSTATUS WINAPI NtCreateIoCompletion( PHANDLE CompletionPort, ACCESS_MASK Desire */ NTSTATUS WINAPI NtSetIoCompletion( HANDLE CompletionPort, ULONG_PTR CompletionKey, ULONG_PTR CompletionValue, NTSTATUS Status, - ULONG NumberOfBytesToTransfer ) + ULONG NumberOfBytesTransferred ) { - FIXME("(%p, %lx, %lx, %x, %d)\n", CompletionPort, CompletionKey, - CompletionValue, Status, NumberOfBytesToTransfer); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS status; + + TRACE("(%p, %lx, %lx, %x, %d)\n", CompletionPort, CompletionKey, + CompletionValue, Status, NumberOfBytesTransferred); + + SERVER_START_REQ( add_completion ) + { + req->handle = CompletionPort; + req->ckey = CompletionKey; + req->cvalue = CompletionValue; + req->status = Status; + req->information = NumberOfBytesTransferred; + status = wine_server_call( req ); + } + SERVER_END_REQ; + return status; } /****************************************************************** @@ -1053,9 +1085,31 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE CompletionPort, PULONG_PTR Completi PULONG_PTR CompletionValue, PIO_STATUS_BLOCK iosb, PLARGE_INTEGER WaitTime ) { - FIXME("(%p, %p, %p, %p, %p)\n", CompletionPort, CompletionKey, + NTSTATUS status; + + TRACE("(%p, %p, %p, %p, %p)\n", CompletionPort, CompletionKey, CompletionValue, iosb, WaitTime); - return STATUS_NOT_IMPLEMENTED; + + for(;;) + { + SERVER_START_REQ( remove_completion ) + { + req->handle = CompletionPort; + if (!(status = wine_server_call( req ))) + { + *CompletionKey = reply->ckey; + *CompletionValue = reply->cvalue; + iosb->Information = reply->information; + iosb->u.Status = reply->status; + } + } + SERVER_END_REQ; + if (status != STATUS_PENDING) break; + + status = NtWaitForSingleObject( CompletionPort, FALSE, WaitTime ); + if (status != WAIT_OBJECT_0) break; + } + return status; } /****************************************************************** @@ -1073,8 +1127,24 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE CompletionPort, PULONG_PTR Completi NTSTATUS WINAPI NtOpenIoCompletion( PHANDLE CompletionPort, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes ) { - FIXME("(%p, 0x%x, %p)\n", CompletionPort, DesiredAccess, ObjectAttributes); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS status; + + TRACE("(%p, 0x%x, %p)\n", CompletionPort, DesiredAccess, ObjectAttributes); + + if (!CompletionPort || !ObjectAttributes || !ObjectAttributes->ObjectName) + return STATUS_INVALID_PARAMETER; + + SERVER_START_REQ( open_completion ) + { + req->access = DesiredAccess; + req->rootdir = ObjectAttributes->RootDirectory; + wine_server_add_data( req, ObjectAttributes->ObjectName->Buffer, + ObjectAttributes->ObjectName->Length ); + if (!(status = wine_server_call( req ))) + *CompletionPort = reply->handle; + } + SERVER_END_REQ; + return status; } /****************************************************************** @@ -1094,7 +1164,36 @@ NTSTATUS WINAPI NtOpenIoCompletion( PHANDLE CompletionPort, ACCESS_MASK DesiredA NTSTATUS WINAPI NtQueryIoCompletion( HANDLE CompletionPort, IO_COMPLETION_INFORMATION_CLASS InformationClass, PVOID CompletionInformation, ULONG BufferLength, PULONG RequiredLength ) { - FIXME("(%p, %d, %p, 0x%x, %p)\n", CompletionPort, InformationClass, CompletionInformation, - BufferLength, RequiredLength); - return STATUS_NOT_IMPLEMENTED; + NTSTATUS status; + + TRACE("(%p, %d, %p, 0x%x, %p)\n", CompletionPort, InformationClass, CompletionInformation, + BufferLength, RequiredLength); + + if (!CompletionInformation) return STATUS_INVALID_PARAMETER; + switch( InformationClass ) + { + case IoCompletionBasicInformation: + { + ULONG *info = (ULONG *)CompletionInformation; + + if (RequiredLength) *RequiredLength = sizeof(*info); + if (BufferLength != sizeof(*info)) + status = STATUS_INFO_LENGTH_MISMATCH; + else + { + SERVER_START_REQ( query_completion ) + { + req->handle = CompletionPort; + if (!(status = wine_server_call( req ))) + *info = reply->depth; + } + SERVER_END_REQ; + } + } + break; + default: + status = STATUS_INVALID_PARAMETER; + break; + } + return status; } diff --git a/dlls/ole32/oleproxy.c b/dlls/ole32/oleproxy.c index e8079411c8f..42dc8d1023d 100644 --- a/dlls/ole32/oleproxy.c +++ b/dlls/ole32/oleproxy.c @@ -402,9 +402,10 @@ static HRESULT WINAPI CFProxy_CreateInstance( hGlobal = GlobalAlloc(GMEM_MOVEABLE|GMEM_NODISCARD|GMEM_SHARE,msg.cbBuffer); memcpy(GlobalLock(hGlobal),msg.Buffer,msg.cbBuffer); hres = CreateStreamOnHGlobal(hGlobal,TRUE,&pStream); - if (hres) { + if (hres != S_OK) { FIXME("CreateStreamOnHGlobal failed with %x\n",hres); IRpcChannelBuffer_FreeBuffer(This->chanbuf,&msg); + GlobalFree(hGlobal); return hres; } hres = IStream_Read(pStream, ppv, sizeof(*ppv), NULL); diff --git a/dlls/ole32/tests/storage32.c b/dlls/ole32/tests/storage32.c index e6c3542453e..2349addcad5 100644 --- a/dlls/ole32/tests/storage32.c +++ b/dlls/ole32/tests/storage32.c @@ -314,9 +314,6 @@ static void test_storage_stream(void) ok(r==S_OK, "failed to seek stream\n"); r = IStream_SetSize(stm,p); ok(r==S_OK, "failed to set pos\n"); - p.u.HighPart = 1; - r = IStream_SetSize(stm,p); - ok(r==STG_E_INVALIDFUNCTION, "setting to invalid pos should fail with STG_E_INVALIDFUNCTION instead of error 0x%08x\n", r); pos.QuadPart = 10; r = IStream_Seek(stm, pos, STREAM_SEEK_SET, &p ); ok(r==S_OK, "failed to seek stream\n"); diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 381b1a9dc1d..b14b5cf3507 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -220,6 +220,8 @@ sub GenerateThunk($$$$$) return "" if $func_ref->[0] eq "glDisable"; return "" if $func_ref->[0] eq "glScissor"; return "" if $func_ref->[0] eq "glViewport"; + return "" if $func_ref->[0] eq "glFinish"; + return "" if $func_ref->[0] eq "glFlush"; # If for opengl_norm.c, generate a nice heading otherwise Patrik won't be happy :-) # Patrik says: Well I would be even happier if a (OPENGL32.@) was added as well. Done. :-) diff --git a/dlls/opengl32/opengl_norm.c b/dlls/opengl32/opengl_norm.c index 65343018300..69acc854201 100644 --- a/dlls/opengl32/opengl_norm.c +++ b/dlls/opengl32/opengl_norm.c @@ -1060,26 +1060,6 @@ void WINAPI wine_glFeedbackBuffer( GLsizei size, GLenum type, GLfloat* buffer ) } /*********************************************************************** - * glFinish (OPENGL32.@) - */ -void WINAPI wine_glFinish( void ) { - TRACE("()\n"); - ENTER_GL(); - glFinish( ); - LEAVE_GL(); -} - -/*********************************************************************** - * glFlush (OPENGL32.@) - */ -void WINAPI wine_glFlush( void ) { - TRACE("()\n"); - ENTER_GL(); - glFlush( ); - LEAVE_GL(); -} - -/*********************************************************************** * glFogf (OPENGL32.@) */ void WINAPI wine_glFogf( GLenum pname, GLfloat param ) { diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 029f3614bfc..deac8dbc118 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -54,6 +54,8 @@ typedef struct wine_wgl_s { GLboolean WINAPI (*p_wglIsEnabled)(GLenum cap); void WINAPI (*p_wglScissor)(GLint x, GLint y, GLsizei width, GLsizei height); void WINAPI (*p_wglViewport)(GLint x, GLint y, GLsizei width, GLsizei height); + void WINAPI (*p_wglFinish)(void); + void WINAPI (*p_wglFlush)(void); } wine_wgl_t; /** global wgl object */ @@ -614,6 +616,24 @@ void WINAPI wine_glViewport( GLint x, GLint y, GLsizei width, GLsizei height ) } /*********************************************************************** + * glFinish (OPENGL32.@) + */ +void WINAPI wine_glFinish( void ) +{ + TRACE("()\n"); + wine_wgl.p_wglFinish(); +} + +/*********************************************************************** + * glFlush (OPENGL32.@) + */ +void WINAPI wine_glFlush( void ) +{ + TRACE("()\n"); + wine_wgl.p_wglFlush(); +} + +/*********************************************************************** * glGetString (OPENGL32.@) */ const GLubyte * WINAPI wine_glGetString( GLenum name ) @@ -705,6 +725,8 @@ static BOOL process_attach(void) wine_wgl.p_wglIsEnabled = (void *)wine_wgl.p_wglGetProcAddress("wglIsEnabled"); wine_wgl.p_wglScissor = (void *)wine_wgl.p_wglGetProcAddress("wglScissor"); wine_wgl.p_wglViewport = (void *)wine_wgl.p_wglGetProcAddress("wglViewport"); + wine_wgl.p_wglFinish = (void *)wine_wgl.p_wglGetProcAddress("wglFinish"); + wine_wgl.p_wglFlush = (void *)wine_wgl.p_wglGetProcAddress("wglFlush"); internal_gl_disabled_extensions[0] = 0; if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\OpenGL", &hkey)) { diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index dff0b5f61b9..f90c353956d 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -1748,7 +1748,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ME_CommitUndo(editor); if (bRepaint) ME_RewrapRepaint(editor); - return 0; + return 1; } case EM_GETCHARFORMAT: { @@ -1983,11 +1983,14 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, return ME_GetTextLengthEx(editor, (GETTEXTLENGTHEX *)wParam); case WM_GETTEXT: { - TEXTRANGEW tr; /* W and A differ only by rng->lpstrText */ - tr.chrg.cpMin = 0; - tr.chrg.cpMax = wParam ? (wParam - 1) : 0; - tr.lpstrText = (WCHAR *)lParam; - return RichEditWndProc_common(hWnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr, unicode); + GETTEXTEX ex; + + ex.cb = wParam; + ex.flags = GT_USECRLF; + ex.codepage = unicode ? 1200 : CP_ACP; + ex.lpDefaultChar = NULL; + ex.lpUsedDefaultChar = NULL; + return RichEditWndProc_common(hWnd, EM_GETTEXTEX, (WPARAM)&ex, lParam, unicode); } case EM_GETTEXTEX: { diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c index 5c0058610b0..7a092c3b854 100644 --- a/dlls/riched20/tests/editor.c +++ b/dlls/riched20/tests/editor.c @@ -366,7 +366,8 @@ static void test_EM_SETTEXTMODE(void) /*EM_SETCHARFORMAT is not yet fully implemented for all WPARAMs in wine; however, SCF_ALL has been implemented*/ - SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); + rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); + ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc); SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) "wine"); /*Select the string "wine"*/ @@ -379,7 +380,8 @@ static void test_EM_SETTEXTMODE(void) /*Reset the formatting to default*/ cf2.dwEffects = CFE_ITALIC^cf2.dwEffects; - SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); + rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); + ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc); /*Clear the text in the control*/ SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) ""); @@ -472,6 +474,7 @@ static void test_TM_PLAINTEXT(void) HWND hwndRichEdit = new_richedit(NULL); CHARFORMAT2 cf2, cf2test; CHARRANGE cr; + int rc = 0; /*Switch to plain text mode*/ @@ -494,7 +497,10 @@ static void test_TM_PLAINTEXT(void) cf2.dwMask = CFM_BOLD | cf2.dwMask; cf2.dwEffects = CFE_BOLD ^ cf2.dwEffects; - SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2); + rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_SELECTION, (LPARAM) &cf2); + todo_wine { + ok(rc == 0, "EM_SETCHARFORMAT returned %d instead of 0\n", rc); + } /*Get the formatting of those characters*/ @@ -534,7 +540,8 @@ static void test_TM_PLAINTEXT(void) SendMessage(hwndRichEdit, EM_GETCHARFORMAT, (WPARAM) SCF_DEFAULT, (LPARAM) &cf2); cf2.dwMask |= CFM_ITALIC; cf2.dwEffects ^= CFE_ITALIC; - SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); + rc = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); + ok(rc == 1, "EM_SETCHARFORMAT returned %d instead of 1\n", rc); /*Set the text in the control to "wine", which will be bold and italicized*/ @@ -910,6 +917,65 @@ static void test_ES_PASSWORD(void) DestroyWindow(hwndRichEdit); } +static void test_WM_SETTEXT() +{ + HWND hwndRichEdit = new_richedit(NULL); + const char * TestItem1 = "TestSomeText"; + const char * TestItem2 = "TestSomeText\r"; + const char * TestItem2_after = "TestSomeText\r\n"; + const char * TestItem3 = "TestSomeText\rSomeMoreText\r"; + const char * TestItem3_after = "TestSomeText\r\nSomeMoreText\r\n"; + char buf[1024] = {0}; + LRESULT result; + + /* This test attempts to show that WM_SETTEXT on a riched20 control causes + any solitary \r to be converted to \r\n on return. Properly paired + \r\n are not affected. + */ + + result = SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem1); + ok (result == 1, "WM_SETTEXT returned %ld instead of 1\n", result); + result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buf); + ok (result == strlen(buf), + "WM_GETTEXT returned %ld instead of expected %u\n", + result, strlen(buf)); + result = strcmp(TestItem1, buf); + ok(result == 0, + "WM_SETTEXT round trip: strcmp = %ld\n", result); + + result = SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem2); + ok (result == 1, "WM_SETTEXT returned %ld instead of 1\n", result); + result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buf); + ok (result == strlen(buf), + "WM_GETTEXT returned %ld instead of expected %u\n", + result, strlen(buf)); + result = strcmp(TestItem2_after, buf); + ok(result == 0, + "WM_SETTEXT round trip: strcmp = %ld\n", result); + + result = SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3); + ok (result == 1, "WM_SETTEXT returned %ld instead of 1\n", result); + result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buf); + ok (result == strlen(buf), + "WM_GETTEXT returned %ld instead of expected %u\n", + result, strlen(buf)); + result = strcmp(TestItem3_after, buf); + ok(result == 0, + "WM_SETTEXT round trip: strcmp = %ld\n", result); + + result = SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3_after); + ok (result == 1, "WM_SETTEXT returned %ld instead of 1\n", result); + result = SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buf); + ok (result == strlen(buf), + "WM_GETTEXT returned %ld instead of expected %u\n", + result, strlen(buf)); + result = strcmp(TestItem3_after, buf); + ok(result == 0, + "WM_SETTEXT round trip: strcmp = %ld\n", result); + + DestroyWindow(hwndRichEdit); +} + static void test_EM_SETTEXTEX(void) { HWND hwndRichEdit = new_richedit(NULL); @@ -918,6 +984,11 @@ static void test_EM_SETTEXTEX(void) WCHAR TestItem1[] = {'T', 'e', 's', 't', 'S', 'o', 'm', 'e', 'T', 'e', 'x', 't', 0}; + WCHAR TestItem2[] = {'T', 'e', 's', 't', + 'S', 'o', 'm', 'e', + 'T', 'e', 'x', 't', + '\r', 0}; + const char * TestItem2_after = "TestSomeText\r\n"; #define MAX_BUF_LEN 1024 WCHAR buf[MAX_BUF_LEN]; int result; @@ -934,6 +1005,25 @@ static void test_EM_SETTEXTEX(void) ok(lstrcmpW(buf, TestItem1) == 0, "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n"); + /* Unlike WM_SETTEXT/WM_GETTEXT pair, EM_SETTEXTEX/EM_GETTEXTEX does not + convert \r to \r\n on return + */ + setText.codepage = 1200; /* no constant for unicode */ + getText.codepage = 1200; /* no constant for unicode */ + getText.cb = MAX_BUF_LEN; + getText.flags = GT_DEFAULT; + + setText.flags = 0; + SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) TestItem2); + SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf); + ok(lstrcmpW(buf, TestItem2) == 0, + "EM_GETTEXTEX results not what was set by EM_SETTEXTEX\n"); + + /* However, WM_GETTEXT *does* see \r\n where EM_GETTEXTEX would see \r */ + SendMessage(hwndRichEdit, WM_GETTEXT, MAX_BUF_LEN, (LPARAM)buf); + ok(strcmp((const char *)buf, TestItem2_after) == 0, + "WM_GETTEXT did *not* see \\r converted to \\r\\n pairs.\n"); + result = SendMessage(hwndRichEdit, EM_SETTEXTEX, (WPARAM)&setText, (LPARAM) NULL); SendMessage(hwndRichEdit, EM_GETTEXTEX, (WPARAM)&getText, (LPARAM) buf); @@ -1389,6 +1479,8 @@ static void test_EM_GETMODIFY(void) cf2.dwMask = CFM_ITALIC | cf2.dwMask; cf2.dwEffects = CFE_ITALIC ^ cf2.dwEffects; SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); + result = SendMessage(hwndRichEdit, EM_SETCHARFORMAT, (WPARAM) SCF_ALL, (LPARAM) &cf2); + ok(result == 1, "EM_SETCHARFORMAT returned %ld instead of 1\n", result); result = SendMessage(hwndRichEdit, EM_GETMODIFY, 0, 0); ok (result != 0, "EM_GETMODIFY returned zero, instead of non-zero for EM_SETCHARFORMAT\n"); @@ -1525,8 +1617,9 @@ static void test_WM_PASTE(void) int result; char buffer[1024] = {0}; const char* text1 = "testing paste\r"; + const char* text1_after = "testing paste\r\n"; const char* text2 = "testing paste\r\rtesting paste"; - const char* text3 = "testing paste\rpaste\rtesting paste"; + const char* text3 = "testing paste\r\npaste\r\ntesting paste"; HWND hwndRichEdit = new_richedit(NULL); SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text1); @@ -1536,7 +1629,7 @@ static void test_WM_PASTE(void) SendMessage(hwndRichEdit, WM_CHAR, 22, 0); /* ctrl-v */ SendMessage(hwndRichEdit, WM_CHAR, 26, 0); /* ctrl-z */ SendMessage(hwndRichEdit, WM_GETTEXT, 1024, (LPARAM) buffer); - result = strcmp(text1, buffer); + result = strcmp(text1_after, buffer); ok(result == 0, "test paste: strcmp = %i\n", result); @@ -2031,6 +2124,7 @@ START_TEST( editor ) test_EM_GETLINE(); test_EM_SCROLLCARET(); test_EM_SCROLL(); + test_WM_SETTEXT(); test_EM_SETTEXTMODE(); test_TM_PLAINTEXT(); test_EM_SETOPTIONS(); diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index bc51c2adc33..2459ccdadd0 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -33,6 +33,7 @@ #include "winnls.h" #include "setupapi.h" #include "wine/debug.h" +#include "wine/list.h" #include "wine/unicode.h" #include "cfgmgr32.h" #include "initguid.h" @@ -85,6 +86,7 @@ static const WCHAR UINumber[] = {'U','I','N','u','m','b','e','r',0}; static const WCHAR UpperFilters[] = {'U','p','p','e','r','F','i','l','t','e','r','s',0}; static const WCHAR LowerFilters[] = {'L','o','w','e','r','F','i','l','t','e','r','s',0}; static const WCHAR Phantom[] = {'P','h','a','n','t','o','m',0}; +static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0}; /* is used to identify if a DeviceInfoSet pointer is valid or not */ @@ -99,22 +101,321 @@ struct DeviceInfoSet SP_DEVINFO_DATA *devices; }; +/* Pointed to by SP_DEVICE_INTERFACE_DATA's Reserved member */ +struct InterfaceInfo +{ + LPWSTR referenceString; + LPWSTR symbolicLink; + PSP_DEVINFO_DATA device; +}; + +/* A device may have multiple instances of the same interface, so this holds + * each instance belonging to a particular interface. + */ +struct InterfaceInstances +{ + GUID guid; + DWORD cInstances; + DWORD cInstancesAllocated; + SP_DEVICE_INTERFACE_DATA *instances; + struct list entry; +}; + /* Pointed to by SP_DEVINFO_DATA's Reserved member */ struct DeviceInfo { - HKEY key; - BOOL phantom; - LPWSTR instanceId; + struct DeviceInfoSet *set; + HKEY key; + BOOL phantom; + LPWSTR instanceId; + struct list interfaces; }; -static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(LPCWSTR instanceId, - BOOL phantom) +static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr) +{ + static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-', + '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2', + 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%', + '0','2','X','}',0}; + + sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], + guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); +} + +static void SETUPDI_FreeInterfaceInstances(struct InterfaceInstances *instances) +{ + DWORD i; + + for (i = 0; i < instances->cInstances; i++) + { + struct InterfaceInfo *ifaceInfo = + (struct InterfaceInfo *)instances->instances[i].Reserved; + + if (ifaceInfo->device && ifaceInfo->device->Reserved) + { + struct DeviceInfo *devInfo = + (struct DeviceInfo *)ifaceInfo->device->Reserved; + + if (devInfo->phantom) + SetupDiDeleteDeviceInterfaceRegKey(devInfo->set, + &instances->instances[i], 0); + } + HeapFree(GetProcessHeap(), 0, ifaceInfo->referenceString); + HeapFree(GetProcessHeap(), 0, ifaceInfo->symbolicLink); + } + HeapFree(GetProcessHeap(), 0, instances->instances); +} + +/* Finds the interface with interface class InterfaceClassGuid in the device. + * Returns TRUE if found, and updates *interface to point to device's + * interfaces member where the given interface was found. + * Returns FALSE if not found. + */ +static BOOL SETUPDI_FindInterface(const struct DeviceInfo *devInfo, + const GUID *InterfaceClassGuid, struct InterfaceInstances **interface) +{ + BOOL found = FALSE; + struct InterfaceInstances *iface; + + TRACE("%s\n", debugstr_guid(InterfaceClassGuid)); + + LIST_FOR_EACH_ENTRY(iface, &devInfo->interfaces, struct InterfaceInstances, + entry) + { + if (IsEqualGUID(&iface->guid, InterfaceClassGuid)) + { + *interface = iface; + found = TRUE; + break; + } + } + TRACE("returning %d (%p)\n", found, found ? *interface : NULL); + return found; +} + +/* Finds the interface instance with reference string ReferenceString in the + * interface instance map. Returns TRUE if found, and updates instanceIndex to + * the index of the interface instance's instances member + * where the given instance was found. Returns FALSE if not found. + */ +static BOOL SETUPDI_FindInterfaceInstance( + const struct InterfaceInstances *instances, + LPCWSTR ReferenceString, DWORD *instanceIndex) +{ + BOOL found = FALSE; + DWORD i; + + TRACE("%s\n", debugstr_w(ReferenceString)); + + for (i = 0; !found && i < instances->cInstances; i++) + { + SP_DEVICE_INTERFACE_DATA *ifaceData = &instances->instances[i]; + struct InterfaceInfo *ifaceInfo = + (struct InterfaceInfo *)ifaceData->Reserved; + + if (!ReferenceString && !ifaceInfo->referenceString) + { + *instanceIndex = i; + found = TRUE; + } + else if (ReferenceString && ifaceInfo->referenceString && + !lstrcmpiW(ifaceInfo->referenceString, ReferenceString)) + { + *instanceIndex = i; + found = TRUE; + } + } + TRACE("returning %d (%d)\n", found, found ? *instanceIndex : 0); + return found; +} + +static LPWSTR SETUPDI_CreateSymbolicLinkPath(LPCWSTR instanceId, + const GUID *InterfaceClassGuid, LPCWSTR ReferenceString) +{ + static const WCHAR fmt[] = {'\\','\\','?','\\','%','s','#','%','s',0}; + WCHAR guidStr[39]; + DWORD len; + LPWSTR ret; + + SETUPDI_GuidToString(InterfaceClassGuid, guidStr); + /* omit length of format specifiers, but include NULL terminator: */ + len = lstrlenW(fmt) - 4 + 1; + len += lstrlenW(instanceId) + lstrlenW(guidStr); + if (ReferenceString) + { + /* space for a hash between string and reference string: */ + len += lstrlenW(ReferenceString) + 1; + } + ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (ret) + { + int printed = sprintfW(ret, fmt, instanceId, guidStr); + LPWSTR ptr; + + /* replace '\\' with '#' after the "\\\\?\\" beginning */ + for (ptr = strchrW(ret + 4, '\\'); ptr; ptr = strchrW(ptr + 1, '\\')) + *ptr = '#'; + if (ReferenceString) + { + ret[printed - 1] = '\\'; + lstrcpyW(ret + printed, ReferenceString); + } + } + return ret; +} + +/* Adds an interface with the given interface class and reference string to + * the device, if it doesn't already exist in the device. If iface is not + * NULL, returns a pointer to the newly added (or already existing) interface. + */ +static BOOL SETUPDI_AddInterfaceInstance(PSP_DEVINFO_DATA DeviceInfoData, + const GUID *InterfaceClassGuid, LPCWSTR ReferenceString, + SP_DEVICE_INTERFACE_DATA **ifaceData) +{ + struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; + BOOL newInterface = FALSE, ret; + struct InterfaceInstances *iface = NULL; + + TRACE("%p %s %s %p\n", devInfo, debugstr_guid(InterfaceClassGuid), + debugstr_w(ReferenceString), iface); + + if (!(ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface))) + { + iface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(struct InterfaceInstances)); + if (iface) + { + list_add_tail(&devInfo->interfaces, &iface->entry); + newInterface = TRUE; + } + } + if (iface) + { + DWORD instanceIndex = 0; + + if (!(ret = SETUPDI_FindInterfaceInstance(iface, ReferenceString, + &instanceIndex))) + { + SP_DEVICE_INTERFACE_DATA *instance = NULL; + + if (!iface->cInstancesAllocated) + { + iface->instances = HeapAlloc(GetProcessHeap(), 0, + sizeof(SP_DEVICE_INTERFACE_DATA)); + if (iface->instances) + instance = &iface->instances[iface->cInstancesAllocated++]; + } + else if (iface->cInstances == iface->cInstancesAllocated) + { + iface->instances = HeapReAlloc(GetProcessHeap(), 0, + iface->instances, + (iface->cInstancesAllocated + 1) * + sizeof(SP_DEVICE_INTERFACE_DATA)); + if (iface->instances) + instance = &iface->instances[iface->cInstancesAllocated++]; + } + else + instance = &iface->instances[iface->cInstances]; + if (instance) + { + struct InterfaceInfo *ifaceInfo = HeapAlloc(GetProcessHeap(), + 0, sizeof(struct InterfaceInfo)); + + if (ifaceInfo) + { + ret = TRUE; + ifaceInfo->device = DeviceInfoData; + ifaceInfo->symbolicLink = SETUPDI_CreateSymbolicLinkPath( + devInfo->instanceId, InterfaceClassGuid, + ReferenceString); + if (ReferenceString) + { + ifaceInfo->referenceString = + HeapAlloc(GetProcessHeap(), 0, + (lstrlenW(ReferenceString) + 1) * + sizeof(WCHAR)); + if (ifaceInfo->referenceString) + lstrcpyW(ifaceInfo->referenceString, + ReferenceString); + else + ret = FALSE; + } + else + ifaceInfo->referenceString = NULL; + if (ret) + { + HKEY key; + + iface->cInstances++; + instance->cbSize = + sizeof(SP_DEVICE_INTERFACE_DATA); + memcpy(&instance->InterfaceClassGuid, + InterfaceClassGuid, sizeof(GUID)); + instance->Flags = SPINT_ACTIVE; /* FIXME */ + instance->Reserved = (ULONG_PTR)ifaceInfo; + if (newInterface) + memcpy(&iface->guid, InterfaceClassGuid, + sizeof(GUID)); + key = SetupDiCreateDeviceInterfaceRegKeyW(devInfo->set, + instance, 0, KEY_WRITE, NULL, NULL); + if (key != INVALID_HANDLE_VALUE) + { + RegSetValueExW(key, SymbolicLink, 0, REG_SZ, + (BYTE *)ifaceInfo->symbolicLink, + lstrlenW(ifaceInfo->symbolicLink) * + sizeof(WCHAR)); + RegCloseKey(key); + } + if (ifaceData) + *ifaceData = instance; + } + else + HeapFree(GetProcessHeap(), 0, ifaceInfo); + } + } + } + else + { + if (ifaceData) + *ifaceData = &iface->instances[instanceIndex]; + } + } + else + ret = FALSE; + TRACE("returning %d\n", ret); + return ret; +} + +static BOOL SETUPDI_SetInterfaceSymbolicLink(SP_DEVICE_INTERFACE_DATA *iface, + LPCWSTR symbolicLink) +{ + struct InterfaceInfo *info = (struct InterfaceInfo *)iface->Reserved; + BOOL ret = FALSE; + + if (info) + { + HeapFree(GetProcessHeap(), 0, info->symbolicLink); + info->symbolicLink = HeapAlloc(GetProcessHeap(), 0, + (lstrlenW(symbolicLink) + 1) * sizeof(WCHAR)); + if (info->symbolicLink) + { + lstrcpyW(info->symbolicLink, symbolicLink); + ret = TRUE; + } + } + return ret; +} + +static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set, + LPCWSTR instanceId, BOOL phantom) { struct DeviceInfo *devInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfo)); if (devInfo) { + devInfo->set = set; devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(instanceId) + 1) * sizeof(WCHAR)); if (devInfo->instanceId) @@ -137,6 +438,7 @@ static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(LPCWSTR instanceId, (LPBYTE)&phantom, sizeof(phantom)); RegCloseKey(enumKey); } + list_init(&devInfo->interfaces); } else { @@ -149,6 +451,8 @@ static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(LPCWSTR instanceId, static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo) { + struct InterfaceInstances *iface, *next; + if (devInfo->key != INVALID_HANDLE_VALUE) RegCloseKey(devInfo->key); if (devInfo->phantom) @@ -165,21 +469,16 @@ static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo) } } HeapFree(GetProcessHeap(), 0, devInfo->instanceId); + LIST_FOR_EACH_ENTRY_SAFE(iface, next, &devInfo->interfaces, + struct InterfaceInstances, entry) + { + list_remove(&iface->entry); + SETUPDI_FreeInterfaceInstances(iface); + HeapFree(GetProcessHeap(), 0, iface); + } HeapFree(GetProcessHeap(), 0, devInfo); } -static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr) -{ - static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-', - '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2', - 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%', - '0','2','X','}',0}; - - sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3, - guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], - guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); -} - /* Adds a device with GUID guid and identifer devInst to set. Allocates a * struct DeviceInfo, and points the returned device info's Reserved member * to it. "Phantom" devices are deleted from the registry when closed. @@ -193,7 +492,7 @@ static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set, SP_DEVINFO_DATA **dev) { BOOL ret = FALSE; - struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(instanceId, + struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(set, instanceId, phantom); TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst, @@ -1087,6 +1386,11 @@ BOOL WINAPI SetupDiRegisterDeviceInfo( return FALSE; } devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; + if (devInfo->set != set) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } if (devInfo->phantom) { devInfo->phantom = FALSE; @@ -1108,9 +1412,10 @@ BOOL WINAPI SetupDiEnumDeviceInfo( TRACE("%p %d %p\n", devinfo, index, info); if(info==NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); return FALSE; - if(info->cbSize < sizeof(*info)) - return FALSE; + } if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE) { struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo; @@ -1226,6 +1531,11 @@ BOOL WINAPI SetupDiGetDeviceInstanceIdW( return FALSE; } devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; + if (devInfo->set != set) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId)); if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1) { @@ -1451,13 +1761,98 @@ HDEVINFO WINAPI SetupDiGetClassDevsA( } MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len); } - ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags); + ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, NULL, NULL, + NULL); + HeapFree(GetProcessHeap(), 0, enumstrW); + +end: + return ret; +} + +/*********************************************************************** + * SetupDiGetClassDevsExA (SETUPAPI.@) + */ +HDEVINFO WINAPI SetupDiGetClassDevsExA( + const GUID *class, + PCSTR enumstr, + HWND parent, + DWORD flags, + HDEVINFO deviceset, + PCSTR machine, + PVOID reserved) +{ + HDEVINFO ret; + LPWSTR enumstrW = NULL, machineW = NULL; + + if (enumstr) + { + int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0); + enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!enumstrW) + { + ret = (HDEVINFO)INVALID_HANDLE_VALUE; + goto end; + } + MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len); + } + if (machine) + { + int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0); + machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!machineW) + { + HeapFree(GetProcessHeap(), 0, enumstrW); + ret = (HDEVINFO)INVALID_HANDLE_VALUE; + goto end; + } + MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len); + } + ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset, + machineW, reserved); HeapFree(GetProcessHeap(), 0, enumstrW); + HeapFree(GetProcessHeap(), 0, machineW); end: return ret; } +static void SETUPDI_AddDeviceInterfaces(SP_DEVINFO_DATA *dev, HKEY key, + const GUID *interface) +{ + DWORD i, len; + WCHAR subKeyName[MAX_PATH]; + LONG l = ERROR_SUCCESS; + + for (i = 0; !l; i++) + { + len = sizeof(subKeyName) / sizeof(subKeyName[0]); + l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL); + if (!l) + { + HKEY subKey; + SP_DEVICE_INTERFACE_DATA *iface = NULL; + + /* The subkey name is the reference string, with a '#' prepended */ + SETUPDI_AddInterfaceInstance(dev, interface, subKeyName + 1, + &iface); + l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey); + if (!l) + { + WCHAR symbolicLink[MAX_PATH]; + DWORD dataType; + + len = sizeof(symbolicLink); + l = RegQueryValueExW(subKey, SymbolicLink, NULL, &dataType, + (BYTE *)symbolicLink, &len); + if (!l && dataType == REG_SZ) + SETUPDI_SetInterfaceSymbolicLink(iface, symbolicLink); + RegCloseKey(subKey); + } + } + } + /* FIXME: find and add all the device's interfaces to the device */ +} + static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet, HKEY key, const GUID *interface, LPCWSTR enumstr) { @@ -1514,12 +1909,11 @@ static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet, deviceClassStr[37] = 0; UuidFromStringW(&deviceClassStr[1], &deviceClass); - SETUPDI_AddDeviceToSet(set, &deviceClass, + if (SETUPDI_AddDeviceToSet(set, &deviceClass, 0 /* FIXME: DevInst */, deviceInst, - FALSE, &dev); - /* FIXME: add this interface, and all the - * device's interfaces, to the device - */ + FALSE, &dev)) + SETUPDI_AddDeviceInterfaces(dev, subKey, + interface); } RegCloseKey(deviceKey); } @@ -1715,11 +2109,29 @@ HDEVINFO WINAPI SetupDiGetClassDevsW( HWND parent, DWORD flags) { + return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL, + NULL); +} + +/*********************************************************************** + * SetupDiGetClassDevsExW (SETUPAPI.@) + */ +HDEVINFO WINAPI SetupDiGetClassDevsExW( + CONST GUID *class, + PCWSTR enumstr, + HWND parent, + DWORD flags, + HDEVINFO deviceset, + PCWSTR machine, + PVOID reserved) +{ static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT | DIGCF_PROFILE; HDEVINFO set; - TRACE("%s %s %p 0x%08x\n", debugstr_guid(class), debugstr_w(enumstr), parent, flags); + TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class), + debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine), + reserved); if (!(flags & DIGCF_ALLCLASSES) && !class) { @@ -1728,11 +2140,16 @@ HDEVINFO WINAPI SetupDiGetClassDevsW( } if (flags & unsupportedFlags) WARN("unsupported flags %08x\n", flags & unsupportedFlags); - /* WinXP always succeeds, returns empty list for unknown classes */ - set = SetupDiCreateDeviceInfoList(class, parent); + if (deviceset) + set = deviceset; + else + set = SetupDiCreateDeviceInfoListExW(class, parent, machine, reserved); if (set) { - if (flags & DIGCF_DEVICEINTERFACE) + if (machine) + FIXME("%s: unimplemented for remote machines\n", + debugstr_w(machine)); + else if (flags & DIGCF_DEVICEINTERFACE) SETUPDI_EnumerateInterfaces(set, class, enumstr, flags); else SETUPDI_EnumerateDevices(set, class, enumstr, flags); @@ -1741,46 +2158,462 @@ HDEVINFO WINAPI SetupDiGetClassDevsW( } /*********************************************************************** - * SetupDiGetClassDevsExW (SETUPAPI.@) + * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@) */ -HDEVINFO WINAPI SetupDiGetClassDevsExW( - CONST GUID *class, - PCWSTR enumstr, - HWND parent, - DWORD flags, - HDEVINFO deviceset, - PCWSTR machine, - PVOID reserved) +BOOL WINAPI SetupDiGetDeviceInfoListDetailA( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData ) { - FIXME("stub\n"); - return NULL; + struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; + + TRACE("%p %p\n", DeviceInfoSet, DevInfoData); + + if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + if (!DevInfoData || + DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID)); + DevInfoData->RemoteMachineHandle = NULL; + DevInfoData->RemoteMachineName[0] = '\0'; + return TRUE; } /*********************************************************************** - * SetupDiEnumDeviceInterfaces (SETUPAPI.@) + * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@) */ -BOOL WINAPI SetupDiEnumDeviceInterfaces( - HDEVINFO devinfo, - PSP_DEVINFO_DATA DeviceInfoData, - CONST GUID * InterfaceClassGuid, - DWORD MemberIndex, - PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) +BOOL WINAPI SetupDiGetDeviceInfoListDetailW( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData ) { - BOOL ret = FALSE; + struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; - FIXME("%p, %p, %s, 0x%08x, %p\n", devinfo, DeviceInfoData, - debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); + TRACE("%p %p\n", DeviceInfoSet, DevInfoData); - if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE) + if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) { - struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo; - if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC) - SetLastError(ERROR_NO_MORE_ITEMS); + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + if (!DevInfoData || + DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID)); + DevInfoData->RemoteMachineHandle = NULL; + DevInfoData->RemoteMachineName[0] = '\0'; + return TRUE; +} + +/*********************************************************************** + * SetupDiCreateDeviceInterfaceA (SETUPAPI.@) + */ +BOOL WINAPI SetupDiCreateDeviceInterfaceA( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_DATA DeviceInfoData, + const GUID *InterfaceClassGuid, + PCSTR ReferenceString, + DWORD CreationFlags, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) +{ + BOOL ret; + LPWSTR ReferenceStringW = NULL; + + TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData, + debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString), + CreationFlags, DeviceInterfaceData); + + if (ReferenceString) + { + ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP); + if (ReferenceStringW == NULL) return FALSE; + } + + ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData, + InterfaceClassGuid, ReferenceStringW, CreationFlags, + DeviceInterfaceData); + + MyFree(ReferenceStringW); + + return ret; +} + +/*********************************************************************** + * SetupDiCreateDeviceInterfaceW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiCreateDeviceInterfaceW( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_DATA DeviceInfoData, + const GUID *InterfaceClassGuid, + PCWSTR ReferenceString, + DWORD CreationFlags, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) +{ + struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; + struct DeviceInfo *devInfo; + SP_DEVICE_INTERFACE_DATA *iface = NULL; + BOOL ret; + + TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData, + debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString), + CreationFlags, DeviceInterfaceData); + + if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) + || !DeviceInfoData->Reserved) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved; + if (devInfo->set != set) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (!InterfaceClassGuid) + { + SetLastError(ERROR_INVALID_USER_BUFFER); + return FALSE; + } + if ((ret = SETUPDI_AddInterfaceInstance(DeviceInfoData, InterfaceClassGuid, + ReferenceString, &iface))) + { + if (DeviceInterfaceData) + { + if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) + { + SetLastError(ERROR_INVALID_USER_BUFFER); + ret = FALSE; + } + else + memcpy(DeviceInterfaceData, iface, sizeof(*iface)); + } + } + return ret; +} + +/*********************************************************************** + * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@) + */ +HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA( + HDEVINFO DeviceInfoSet, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, + DWORD Reserved, + REGSAM samDesired, + HINF InfHandle, + PCSTR InfSectionName) +{ + HKEY key; + PWSTR InfSectionNameW = NULL; + + TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved, + samDesired, InfHandle, InfSectionName); + if (InfHandle) + { + if (!InfSectionName) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP); + if (!InfSectionNameW) + return INVALID_HANDLE_VALUE; + } + key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet, + DeviceInterfaceData, Reserved, samDesired, InfHandle, + InfSectionNameW); + MyFree(InfSectionNameW); + return key; +} + +static PWSTR SETUPDI_GetInstancePath(struct InterfaceInfo *ifaceInfo) +{ + static const WCHAR hash[] = {'#',0}; + PWSTR instancePath = NULL; + + if (ifaceInfo->referenceString) + { + instancePath = HeapAlloc(GetProcessHeap(), 0, + (lstrlenW(ifaceInfo->referenceString) + 2) * sizeof(WCHAR)); + if (instancePath) + { + lstrcpyW(instancePath, hash); + lstrcatW(instancePath, ifaceInfo->referenceString); + } else - SetLastError(ERROR_INVALID_HANDLE); + SetLastError(ERROR_OUTOFMEMORY); + } + else + { + instancePath = HeapAlloc(GetProcessHeap(), 0, + (lstrlenW(hash) + 1) * sizeof(WCHAR)); + if (instancePath) + lstrcpyW(instancePath, hash); + } + return instancePath; +} + +/*********************************************************************** + * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@) + */ +HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW( + HDEVINFO DeviceInfoSet, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, + DWORD Reserved, + REGSAM samDesired, + HINF InfHandle, + PCWSTR InfSectionName) +{ + struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; + HKEY key = INVALID_HANDLE_VALUE, interfacesKey; + LONG l; + + TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved, + samDesired, InfHandle, InfSectionName); + + if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE || + set->magic != SETUP_DEVICE_INFO_SET_MAGIC) + { + SetLastError(ERROR_INVALID_HANDLE); + return INVALID_HANDLE_VALUE; + } + if (!DeviceInterfaceData || + DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || + !DeviceInterfaceData->Reserved) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + if (InfHandle && !InfSectionName) + { + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; + } + if (!(l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, DeviceClasses, 0, NULL, 0, + samDesired, NULL, &interfacesKey, NULL))) + { + HKEY parent; + WCHAR bracedGuidString[39]; + + SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, + bracedGuidString); + if (!(l = RegCreateKeyExW(interfacesKey, bracedGuidString, 0, NULL, 0, + samDesired, NULL, &parent, NULL))) + { + struct InterfaceInfo *ifaceInfo = + (struct InterfaceInfo *)DeviceInterfaceData->Reserved; + PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo); + + if (instancePath) + { + LONG l; + + l = RegCreateKeyExW(parent, instancePath, 0, NULL, 0, + samDesired, NULL, &key, NULL); + if (l) + { + SetLastError(l); + key = INVALID_HANDLE_VALUE; + } + else if (InfHandle) + FIXME("INF section installation unsupported\n"); + } + HeapFree(GetProcessHeap(), 0, instancePath); + RegCloseKey(parent); + } + else + SetLastError(l); + RegCloseKey(interfacesKey); } else + SetLastError(l); + return key; +} + +/*********************************************************************** + * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@) + */ +BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey( + HDEVINFO DeviceInfoSet, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, + DWORD Reserved) +{ + struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; + HKEY parent; + BOOL ret = FALSE; + + TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved); + + if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE || + set->magic != SETUP_DEVICE_INFO_SET_MAGIC) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + if (!DeviceInterfaceData || + DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || + !DeviceInterfaceData->Reserved) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + parent = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, + KEY_ALL_ACCESS, DIOCR_INTERFACE, NULL, NULL); + if (parent != INVALID_HANDLE_VALUE) + { + struct InterfaceInfo *ifaceInfo = + (struct InterfaceInfo *)DeviceInterfaceData->Reserved; + PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo); + + if (instancePath) + { + LONG l = RegDeleteKeyW(parent, instancePath); + + if (l) + SetLastError(l); + else + ret = TRUE; + HeapFree(GetProcessHeap(), 0, instancePath); + } + RegCloseKey(parent); + } + return ret; +} + +/*********************************************************************** + * SetupDiEnumDeviceInterfaces (SETUPAPI.@) + * + * PARAMS + * DeviceInfoSet [I] Set of devices from which to enumerate + * interfaces + * DeviceInfoData [I] (Optional) If specified, a specific device + * instance from which to enumerate interfaces. + * If it isn't specified, all interfaces for all + * devices in the set are enumerated. + * InterfaceClassGuid [I] The interface class to enumerate. + * MemberIndex [I] An index of the interface instance to enumerate. + * A caller should start with MemberIndex set to 0, + * and continue until the function fails with + * ERROR_NO_MORE_ITEMS. + * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize + * member must be set to + * sizeof(SP_DEVICE_INTERFACE_DATA). + * + * RETURNS + * Success: non-zero value. + * Failure: FALSE. Call GetLastError() for more info. + */ +BOOL WINAPI SetupDiEnumDeviceInterfaces( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_DATA DeviceInfoData, + CONST GUID * InterfaceClassGuid, + DWORD MemberIndex, + PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) +{ + struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; + BOOL ret = FALSE; + + TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData, + debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); + + if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE || + set->magic != SETUP_DEVICE_INFO_SET_MAGIC) + { SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) || + !DeviceInfoData->Reserved)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (!DeviceInterfaceData || + DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (DeviceInfoData) + { + struct DeviceInfo *devInfo = + (struct DeviceInfo *)DeviceInfoData->Reserved; + struct InterfaceInstances *iface; + + if ((ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface))) + { + if (MemberIndex < iface->cInstances) + memcpy(DeviceInterfaceData, &iface->instances[MemberIndex], + sizeof(SP_DEVICE_INTERFACE_DATA)); + else + { + SetLastError(ERROR_NO_MORE_ITEMS); + ret = FALSE; + } + } + else + SetLastError(ERROR_NO_MORE_ITEMS); + } + else + { + DWORD i, cEnumerated = 0; + BOOL found = FALSE; + + for (i = 0; !found && cEnumerated < MemberIndex + 1 && + i < set->cDevices; i++) + { + struct DeviceInfo *devInfo = + (struct DeviceInfo *)set->devices[i].Reserved; + struct InterfaceInstances *iface; + + if (SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)) + { + if (cEnumerated + iface->cInstances < MemberIndex + 1) + cEnumerated += iface->cInstances; + else + { + DWORD instanceIndex = MemberIndex - cEnumerated; + + memcpy(DeviceInterfaceData, + &iface->instances[instanceIndex], + sizeof(SP_DEVICE_INTERFACE_DATA)); + cEnumerated += instanceIndex + 1; + found = TRUE; + ret = TRUE; + } + } + } + if (!found) + SetLastError(ERROR_NO_MORE_ITEMS); + } return ret; } @@ -1835,13 +2668,65 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailA( PDWORD RequiredSize, PSP_DEVINFO_DATA DeviceInfoData) { + struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; + struct InterfaceInfo *info; + DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + + 1; BOOL ret = FALSE; - FIXME("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet, + TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet, DeviceInterfaceData, DeviceInterfaceDetailData, DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); - SetLastError(ERROR_INVALID_HANDLE); + if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE || + set->magic != SETUP_DEVICE_INFO_SET_MAGIC) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + if (!DeviceInterfaceData || + DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || + !DeviceInterfaceData->Reserved) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize < + offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(char) || + DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))) + { + SetLastError(ERROR_INVALID_USER_BUFFER); + return FALSE; + } + if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize) + { + SetLastError(ERROR_INVALID_USER_BUFFER); + return FALSE; + } + info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved; + if (info->symbolicLink) + bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1, + NULL, 0, NULL, NULL); + if (DeviceInterfaceDetailDataSize >= bytesNeeded) + { + if (info->symbolicLink) + WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1, + DeviceInterfaceDetailData->DevicePath, + DeviceInterfaceDetailDataSize - + offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath), + NULL, NULL); + else + DeviceInterfaceDetailData->DevicePath[0] = '\0'; + if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA)) + memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA)); + ret = TRUE; + } + else + { + if (RequiredSize) + *RequiredSize = bytesNeeded; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + } return ret; } @@ -1856,10 +2741,61 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailW( PDWORD RequiredSize, PSP_DEVINFO_DATA DeviceInfoData) { - FIXME("(%p, %p, %p, %d, %p, %p): stub\n", DeviceInfoSet, + struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet; + struct InterfaceInfo *info; + DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + + sizeof(WCHAR); /* include NULL terminator */ + BOOL ret = FALSE; + + TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet, DeviceInterfaceData, DeviceInterfaceDetailData, DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); - return FALSE; + + if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE || + set->magic != SETUP_DEVICE_INFO_SET_MAGIC) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + if (!DeviceInterfaceData || + DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) || + !DeviceInterfaceData->Reserved) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize < + offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR) || + DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))) + { + SetLastError(ERROR_INVALID_USER_BUFFER); + return FALSE; + } + if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize) + { + SetLastError(ERROR_INVALID_USER_BUFFER); + return FALSE; + } + info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved; + if (info->symbolicLink) + bytesNeeded += lstrlenW(info->symbolicLink); + if (DeviceInterfaceDetailDataSize >= bytesNeeded) + { + if (info->symbolicLink) + lstrcpyW(DeviceInterfaceDetailData->DevicePath, info->symbolicLink); + else + DeviceInterfaceDetailData->DevicePath[0] = '\0'; + if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA)) + memcpy(DeviceInfoData, info->device, sizeof(SP_DEVINFO_DATA)); + ret = TRUE; + } + else + { + if (RequiredSize) + *RequiredSize = bytesNeeded; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + } + return ret; } struct PropertyMapEntry @@ -2337,10 +3273,10 @@ HKEY WINAPI SetupDiOpenClassRegKeyExW( PCWSTR MachineName, PVOID Reserved) { - WCHAR bracedGuidString[39]; HKEY hClassesKey; - HKEY hClassKey; + HKEY key; LPCWSTR lpKeyName; + LONG l; if (MachineName != NULL) { @@ -2363,33 +3299,49 @@ HKEY WINAPI SetupDiOpenClassRegKeyExW( return INVALID_HANDLE_VALUE; } - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, - lpKeyName, - 0, - KEY_ALL_ACCESS, - &hClassesKey)) + if (!ClassGuid) { - return INVALID_HANDLE_VALUE; + if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + lpKeyName, + 0, + samDesired, + &hClassesKey))) + { + SetLastError(l); + hClassesKey = INVALID_HANDLE_VALUE; + } + key = hClassesKey; } - - if (ClassGuid == NULL) - return hClassesKey; - - SETUPDI_GuidToString(ClassGuid, bracedGuidString); - - if (RegOpenKeyExW(hClassesKey, - bracedGuidString, - 0, - KEY_ALL_ACCESS, - &hClassKey)) + else { - RegCloseKey(hClassesKey); - return INVALID_HANDLE_VALUE; - } + WCHAR bracedGuidString[39]; - RegCloseKey(hClassesKey); + SETUPDI_GuidToString(ClassGuid, bracedGuidString); - return hClassKey; + if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + lpKeyName, + 0, + samDesired, + &hClassesKey))) + { + if ((l = RegOpenKeyExW(hClassesKey, + bracedGuidString, + 0, + samDesired, + &key))) + { + SetLastError(l); + key = INVALID_HANDLE_VALUE; + } + RegCloseKey(hClassesKey); + } + else + { + SetLastError(l); + key = INVALID_HANDLE_VALUE; + } + } + return key; } /*********************************************************************** diff --git a/dlls/setupapi/setupapi.spec b/dlls/setupapi/setupapi.spec index 7f8b3dda007..f9589b1342b 100644 --- a/dlls/setupapi/setupapi.spec +++ b/dlls/setupapi/setupapi.spec @@ -288,9 +288,14 @@ @ stdcall SetupDiCreateDeviceInfoListExA(ptr long str ptr) @ stdcall SetupDiCreateDeviceInfoListExW(ptr long str ptr) @ stdcall SetupDiCreateDeviceInfoW(long wstr ptr wstr long long ptr) +@ stdcall SetupDiCreateDeviceInterfaceA(ptr ptr ptr str long ptr) +@ stdcall SetupDiCreateDeviceInterfaceW(ptr ptr ptr wstr long ptr) +@ stdcall SetupDiCreateDeviceInterfaceRegKeyA(ptr ptr long long ptr ptr) +@ stdcall SetupDiCreateDeviceInterfaceRegKeyW(ptr ptr long long ptr ptr) @ stub SetupDiDeleteDevRegKey @ stub SetupDiDeleteDeviceInfo @ stub SetupDiDeleteDeviceInterfaceData +@ stdcall SetupDiDeleteDeviceInterfaceRegKey(ptr ptr long) @ stub SetupDiDeleteDeviceRegKey @ stub SetupDiDestroyClassImageList @ stdcall SetupDiDestroyDeviceInfoList(long) diff --git a/dlls/setupapi/stubs.c b/dlls/setupapi/stubs.c index bf3fa90936d..de1fec19f05 100644 --- a/dlls/setupapi/stubs.c +++ b/dlls/setupapi/stubs.c @@ -50,35 +50,6 @@ DWORD WINAPI suErrorToIds16( WORD w1, WORD w2 ) } /*********************************************************************** - * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetDeviceInfoListDetailA(HDEVINFO devinfo, PSP_DEVINFO_LIST_DETAIL_DATA_A devinfo_data ) -{ - FIXME("\n"); - return FALSE; -} - -/*********************************************************************** - * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@) - */ -BOOL WINAPI SetupDiGetDeviceInfoListDetailW(HDEVINFO devinfo, PSP_DEVINFO_LIST_DETAIL_DATA_W devinfo_data ) -{ - FIXME("\n"); - return FALSE; -} - -/*********************************************************************** - * (SETUPAPI.@) - * - * NO WINAPI in description given - */ -HDEVINFO WINAPI SetupDiGetClassDevsExA(const GUID *class, PCSTR filter, HWND parent, DWORD flags, HDEVINFO deviceset, PCSTR machine, PVOID reserved) -{ - FIXME("filter %s machine %s\n",debugstr_a(filter),debugstr_a(machine)); - return FALSE; -} - -/*********************************************************************** * CM_Connect_MachineW (SETUPAPI.@) */ DWORD WINAPI CM_Connect_MachineW(LPCWSTR name, void * machine) diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 0ef9047a68b..0b58e4e4f4a 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -35,11 +35,14 @@ static HMODULE hSetupAPI; static HDEVINFO (WINAPI *pSetupDiCreateDeviceInfoList)(GUID*,HWND); static HDEVINFO (WINAPI *pSetupDiCreateDeviceInfoListExW)(GUID*,HWND,PCWSTR,PVOID); +static BOOL (WINAPI *pSetupDiCreateDeviceInterfaceA)(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, PCSTR, DWORD, PSP_DEVICE_INTERFACE_DATA); static BOOL (WINAPI *pSetupDiDestroyDeviceInfoList)(HDEVINFO); static BOOL (WINAPI *pSetupDiEnumDeviceInfo)(HDEVINFO, DWORD, PSP_DEVINFO_DATA); +static BOOL (WINAPI *pSetupDiEnumDeviceInterfaces)(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, DWORD, PSP_DEVICE_INTERFACE_DATA); static HKEY (WINAPI *pSetupDiOpenClassRegKeyExA)(GUID*,REGSAM,DWORD,PCSTR,PVOID); static BOOL (WINAPI *pSetupDiCreateDeviceInfoA)(HDEVINFO, PCSTR, GUID *, PCSTR, HWND, DWORD, PSP_DEVINFO_DATA); static BOOL (WINAPI *pSetupDiGetDeviceInstanceIdA)(HDEVINFO, PSP_DEVINFO_DATA, PSTR, DWORD, PDWORD); +static BOOL (WINAPI *pSetupDiGetDeviceInterfaceDetailA)(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA); static BOOL (WINAPI *pSetupDiRegisterDeviceInfo)(HDEVINFO, PSP_DEVINFO_DATA, DWORD, PSP_DETSIG_CMPPROC, PVOID, PSP_DEVINFO_DATA); static void init_function_pointers(void) @@ -49,9 +52,12 @@ static void init_function_pointers(void) pSetupDiCreateDeviceInfoA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoA"); pSetupDiCreateDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoList"); pSetupDiCreateDeviceInfoListExW = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInfoListExW"); + pSetupDiCreateDeviceInterfaceA = (void *)GetProcAddress(hSetupAPI, "SetupDiCreateDeviceInterfaceA"); pSetupDiDestroyDeviceInfoList = (void *)GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList"); pSetupDiEnumDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo"); + pSetupDiEnumDeviceInterfaces = (void *)GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInterfaces"); pSetupDiGetDeviceInstanceIdA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInstanceIdA"); + pSetupDiGetDeviceInterfaceDetailA = (void *)GetProcAddress(hSetupAPI, "SetupDiGetDeviceInterfaceDetailA"); pSetupDiOpenClassRegKeyExA = (void *)GetProcAddress(hSetupAPI, "SetupDiOpenClassRegKeyExA"); pSetupDiRegisterDeviceInfo = (void *)GetProcAddress(hSetupAPI, "SetupDiRegisterDeviceInfo"); } @@ -331,6 +337,166 @@ static void testRegisterDeviceInfo(void) } } +static void testCreateDeviceInterface(void) +{ + BOOL ret; + GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04, + 0x00,0x11,0x95,0x5c,0x2b,0xdb}}; + HDEVINFO set; + + if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList || + !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA || + !pSetupDiEnumDeviceInterfaces) + { + skip("No SetupDiCreateDeviceInterfaceA\n"); + return; + } + SetLastError(0xdeadbeef); + ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, NULL, NULL, 0, NULL); + ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, + "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = pSetupDiCreateDeviceInterfaceA(NULL, NULL, &guid, NULL, 0, NULL); + ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, + "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + set = pSetupDiCreateDeviceInfoList(&guid, NULL); + ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError()); + if (set) + { + SP_DEVINFO_DATA devInfo = { 0 }; + SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), + { 0 } }; + DWORD i; + + SetLastError(0xdeadbeef); + ret = pSetupDiCreateDeviceInterfaceA(set, NULL, NULL, NULL, 0, NULL); + ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0, + NULL); + ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + devInfo.cbSize = sizeof(devInfo); + ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid, + NULL, NULL, 0, &devInfo); + ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, NULL, NULL, 0, + NULL); + ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, + "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); + ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, + NULL); + ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); + /* Creating the same interface a second time succeeds */ + ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, + NULL); + ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); + ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, "Oogah", 0, + NULL); + ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); + ret = pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, 0, + &interfaceData); + ok(ret, "SetupDiEnumDeviceInterfaces failed: %d\n", GetLastError()); + i = 0; + while (pSetupDiEnumDeviceInterfaces(set, &devInfo, &guid, i, + &interfaceData)) + i++; + ok(i == 2, "expected 2 interfaces, got %d\n", i); + ok(GetLastError() == ERROR_NO_MORE_ITEMS, + "SetupDiEnumDeviceInterfaces failed: %08x\n", GetLastError()); + pSetupDiDestroyDeviceInfoList(set); + } +} + +static void testGetDeviceInterfaceDetail(void) +{ + BOOL ret; + GUID guid = {0x6a55b5a4, 0x3f65, 0x11db, {0xb7,0x04, + 0x00,0x11,0x95,0x5c,0x2b,0xdb}}; + HDEVINFO set; + + if (!pSetupDiCreateDeviceInfoList || !pSetupDiDestroyDeviceInfoList || + !pSetupDiCreateDeviceInfoA || !pSetupDiCreateDeviceInterfaceA || + !pSetupDiGetDeviceInterfaceDetailA) + { + skip("No SetupDiGetDeviceInterfaceDetailA\n"); + return; + } + SetLastError(0xdeadbeef); + ret = pSetupDiGetDeviceInterfaceDetailA(NULL, NULL, NULL, 0, NULL, NULL); + ok(!ret && GetLastError() == ERROR_INVALID_HANDLE, + "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + set = pSetupDiCreateDeviceInfoList(&guid, NULL); + ok(set != NULL, "SetupDiCreateDeviceInfoList failed: %d\n", GetLastError()); + if (set) + { + SP_DEVINFO_DATA devInfo = { sizeof(devInfo), { 0 } }; + SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof(interfaceData), + { 0 } }; + DWORD size = 0; + + SetLastError(0xdeadbeef); + ret = pSetupDiGetDeviceInterfaceDetailA(set, NULL, NULL, 0, NULL, + NULL); + ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + ret = pSetupDiCreateDeviceInfoA(set, "ROOT\\LEGACY_BOGUS\\0000", &guid, + NULL, NULL, 0, &devInfo); + ok(ret, "SetupDiCreateDeviceInfoA failed: %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = pSetupDiCreateDeviceInterfaceA(set, &devInfo, &guid, NULL, 0, + &interfaceData); + ok(ret, "SetupDiCreateDeviceInterfaceA failed: %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, + 0, NULL, NULL); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, + 100, NULL, NULL); + ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, + "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, NULL, + 0, &size, NULL); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + static const char path[] = + "\\\\?\\root#legacy_bogus#0000#{6a55b5a4-3f65-11db-b704-0011955c2bdb}"; + LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size); + SP_DEVICE_INTERFACE_DETAIL_DATA_A *detail = + (SP_DEVICE_INTERFACE_DETAIL_DATA_A *)buf; + + detail->cbSize = 0; + SetLastError(0xdeadbeef); + ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail, + size, &size, NULL); + ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, + "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); + detail->cbSize = size; + SetLastError(0xdeadbeef); + ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail, + size, &size, NULL); + ok(!ret && GetLastError() == ERROR_INVALID_USER_BUFFER, + "Expected ERROR_INVALID_USER_BUFFER, got %08x\n", GetLastError()); + detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); + ret = pSetupDiGetDeviceInterfaceDetailA(set, &interfaceData, detail, + size, &size, NULL); + ok(ret, "SetupDiGetDeviceInterfaceDetailA failed: %d\n", + GetLastError()); + ok(!lstrcmpiA(path, detail->DevicePath), "Unexpected path %s\n", + detail->DevicePath); + HeapFree(GetProcessHeap(), 0, buf); + } + pSetupDiDestroyDeviceInfoList(set); + } +} + START_TEST(devinst) { init_function_pointers(); @@ -347,4 +513,6 @@ START_TEST(devinst) testCreateDeviceInfo(); testGetDeviceInstanceId(); testRegisterDeviceInfo(); + testCreateDeviceInterface(); + testGetDeviceInterfaceDetail(); } diff --git a/dlls/shdocvw/shdocvw.h b/dlls/shdocvw/shdocvw.h index 0e2a739c6aa..28637bf0920 100644 --- a/dlls/shdocvw/shdocvw.h +++ b/dlls/shdocvw/shdocvw.h @@ -131,6 +131,7 @@ struct WebBrowser { VARIANT_BOOL address_bar; VARIANT_BOOL status_bar; VARIANT_BOOL tool_bar; + VARIANT_BOOL full_screen; DocHost doc_host; }; diff --git a/dlls/shdocvw/tests/webbrowser.c b/dlls/shdocvw/tests/webbrowser.c index 8f805051a0d..2b3815432af 100644 --- a/dlls/shdocvw/tests/webbrowser.c +++ b/dlls/shdocvw/tests/webbrowser.c @@ -1094,6 +1094,46 @@ static void test_ie_funcs(IUnknown *unk) hres = IWebBrowser2_put_ToolBar(wb, VARIANT_TRUE); ok(hres == S_OK, "put_ToolBar failed: %08x\n", hres); + /* FullScreen */ + + hres = IWebBrowser2_get_FullScreen(wb, &b); + ok(hres == S_OK, "get_FullScreen failed: %08x\n", hres); + ok(b == VARIANT_FALSE, "b=%x\n", b); + + hres = IWebBrowser2_put_FullScreen(wb, VARIANT_TRUE); + ok(hres == S_OK, "put_FullScreen failed: %08x\n", hres); + + hres = IWebBrowser2_get_FullScreen(wb, &b); + ok(hres == S_OK, "get_FullScreen failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "b=%x\n", b); + + hres = IWebBrowser2_put_FullScreen(wb, 100); + ok(hres == S_OK, "put_FullScreen failed: %08x\n", hres); + + hres = IWebBrowser2_get_FullScreen(wb, &b); + ok(hres == S_OK, "get_FullScreen failed: %08x\n", hres); + ok(b == VARIANT_TRUE, "b=%x\n", b); + + hres = IWebBrowser2_put_FullScreen(wb, VARIANT_FALSE); + ok(hres == S_OK, "put_FullScreen failed: %08x\n", hres); + + /* Resizable */ + + b = 0x100; + hres = IWebBrowser2_get_Resizable(wb, &b); + ok(hres == E_NOTIMPL, "get_Resizable failed: %08x\n", hres); + ok(b == 0x100, "b=%x\n", b); + + hres = IWebBrowser2_put_Resizable(wb, VARIANT_TRUE); + ok(hres == S_OK, "put_Resizable failed: %08x\n", hres); + + hres = IWebBrowser2_put_Resizable(wb, VARIANT_FALSE); + ok(hres == S_OK, "put_Resizable failed: %08x\n", hres); + + hres = IWebBrowser2_get_Resizable(wb, &b); + ok(hres == E_NOTIMPL, "get_Resizable failed: %08x\n", hres); + ok(b == 0x100, "b=%x\n", b); + IWebBrowser2_Release(wb); } diff --git a/dlls/shdocvw/webbrowser.c b/dlls/shdocvw/webbrowser.c index ff7f699e3c5..c9af82f7448 100644 --- a/dlls/shdocvw/webbrowser.c +++ b/dlls/shdocvw/webbrowser.c @@ -638,15 +638,21 @@ static HRESULT WINAPI WebBrowser_put_MenuBar(IWebBrowser2 *iface, VARIANT_BOOL V static HRESULT WINAPI WebBrowser_get_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL *pbFullScreen) { WebBrowser *This = WEBBROWSER_THIS(iface); - FIXME("(%p)->(%p)\n", This, pbFullScreen); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, pbFullScreen); + + *pbFullScreen = This->full_screen; + return S_OK; } static HRESULT WINAPI WebBrowser_put_FullScreen(IWebBrowser2 *iface, VARIANT_BOOL bFullScreen) { WebBrowser *This = WEBBROWSER_THIS(iface); - FIXME("(%p)->(%x)\n", This, bFullScreen); - return E_NOTIMPL; + + TRACE("(%p)->(%x)\n", This, bFullScreen); + + This->full_screen = bFullScreen ? VARIANT_TRUE : VARIANT_FALSE; + return S_OK; } static HRESULT WINAPI WebBrowser_Navigate2(IWebBrowser2 *iface, VARIANT *URL, VARIANT *Flags, @@ -819,15 +825,21 @@ static HRESULT WINAPI WebBrowser_put_AddressBar(IWebBrowser2 *iface, VARIANT_BOO static HRESULT WINAPI WebBrowser_get_Resizable(IWebBrowser2 *iface, VARIANT_BOOL *Value) { WebBrowser *This = WEBBROWSER_THIS(iface); - FIXME("(%p)->(%p)\n", This, Value); + + TRACE("(%p)->(%p)\n", This, Value); + + /* It's InternetExplorer object's method. We have nothing to do here. */ return E_NOTIMPL; } static HRESULT WINAPI WebBrowser_put_Resizable(IWebBrowser2 *iface, VARIANT_BOOL Value) { WebBrowser *This = WEBBROWSER_THIS(iface); - FIXME("(%p)->(%x)\n", This, Value); - return E_NOTIMPL; + + TRACE("(%p)->(%x)\n", This, Value); + + /* It's InternetExplorer object's method. We have nothing to do here. */ + return S_OK; } #undef WEBBROWSER_THIS @@ -927,6 +939,7 @@ static HRESULT WebBrowser_Create(INT version, IUnknown *pOuter, REFIID riid, voi ret->address_bar = VARIANT_TRUE; ret->status_bar = VARIANT_TRUE; ret->tool_bar = VARIANT_TRUE; + ret->full_screen = VARIANT_FALSE; WebBrowser_OleObject_Init(ret); WebBrowser_ViewObject_Init(ret); diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec index 9beb6d3acab..6928538bcfa 100644 --- a/dlls/shell32/shell32.spec +++ b/dlls/shell32/shell32.spec @@ -156,7 +156,7 @@ 165 stdcall -noname SHCreateDirectory(long ptr) 166 stdcall -noname CallCPLEntry16(long long long long long long) 167 stdcall -noname SHAddFromPropSheetExtArray(long long long) - 168 stdcall -noname SHCreatePropSheetExtArray(long str long) + 168 stdcall -noname SHCreatePropSheetExtArray(long wstr long) 169 stdcall -noname SHDestroyPropSheetExtArray(long) 170 stdcall -noname SHReplaceFromPropSheetExtArray(long long long long) 171 stdcall -noname PathCleanupSpec(ptr ptr) @@ -182,7 +182,7 @@ 191 stdcall -noname SHUpdateImageA(str long long long) 192 stdcall -noname SHUpdateImageW(wstr long long long) 193 stdcall -noname SHHandleUpdateImage(ptr) - 194 stub SHCreatePropSheetExtArrayEx + 194 stdcall -noname SHCreatePropSheetExtArrayEx(long wstr long ptr) 195 stdcall -noname SHFree(ptr) 196 stdcall -noname SHAlloc(long) 197 stub SHGlobalDefect diff --git a/dlls/shell32/shellord.c b/dlls/shell32/shellord.c index 52c2934c803..e3b77cfcf78 100644 --- a/dlls/shell32/shellord.c +++ b/dlls/shell32/shellord.c @@ -1588,6 +1588,14 @@ UINT WINAPI SHAddFromPropSheetExtArray(HPSXA hpsxa, LPFNADDPROPSHEETPAGE lpfnAdd */ HPSXA WINAPI SHCreatePropSheetExtArray(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface) { + return SHCreatePropSheetExtArrayEx(hKey, pszSubKey, max_iface, NULL); +} + +/************************************************************************* + * SHCreatePropSheetExtArrayEx [SHELL32.194] + */ +HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj) +{ static const WCHAR szPropSheetSubKey[] = {'s','h','e','l','l','e','x','\\','P','r','o','p','e','r','t','y','S','h','e','e','t','H','a','n','d','l','e','r','s',0}; WCHAR szHandler[64]; DWORD dwHandlerLen; @@ -1652,7 +1660,7 @@ HPSXA WINAPI SHCreatePropSheetExtArray(HKEY hKey, LPCWSTR pszSubKey, UINT max_if { if (SUCCEEDED(pspsx->lpVtbl->QueryInterface(pspsx, &IID_IShellExtInit, (PVOID *)&psxi))) { - if (SUCCEEDED(psxi->lpVtbl->Initialize(psxi, NULL, NULL, hKey))) + if (SUCCEEDED(psxi->lpVtbl->Initialize(psxi, NULL, pDataObj, hKey))) { /* Add the IShellPropSheetExt instance to the array */ psxa->pspsx[psxa->uiCount++] = pspsx; diff --git a/dlls/shell32/shlview.c b/dlls/shell32/shlview.c index 6dd27da30cf..b1d8e34459a 100644 --- a/dlls/shell32/shlview.c +++ b/dlls/shell32/shlview.c @@ -68,6 +68,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell); +static const WCHAR SV_CLASS_NAME[] = {'S','H','E','L','L','D','L','L','_','D','e','f','V','i','e','w',0}; + typedef struct { BOOL bIsAscending; INT nHeaderID; @@ -290,8 +292,8 @@ static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove) TRACE("(%p)\n", This); - tmpstyle = GetWindowLongA(This->hWndList, GWL_STYLE); - SetWindowLongA(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove)); + tmpstyle = GetWindowLongW(This->hWndList, GWL_STYLE); + SetWindowLongW(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove)); } /********************************************************** @@ -324,8 +326,8 @@ static BOOL ShellView_CreateList (IShellViewImpl * This) if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE) dwExStyle &= ~WS_EX_CLIENTEDGE; - This->hWndList=CreateWindowExA( dwExStyle, - WC_LISTVIEWA, + This->hWndList=CreateWindowExW( dwExStyle, + WC_LISTVIEWW, NULL, dwStyle, 0,0,0,0, @@ -526,11 +528,11 @@ static int LV_FindItemByPidl( IShellViewImpl * This, LPCITEMIDLIST pidl) { - LVITEMA lvItem; + LVITEMW lvItem; lvItem.iSubItem = 0; lvItem.mask = LVIF_PARAM; for(lvItem.iItem = 0; - SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem); + SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem); lvItem.iItem++) { LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam; @@ -548,7 +550,7 @@ static int LV_FindItemByPidl( */ static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl) { - LVITEMA lvItem; + LVITEMW lvItem; TRACE("(%p)(pidl=%p)\n", This, pidl); @@ -556,9 +558,9 @@ static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl) lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/ lvItem.iSubItem = 0; lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/ - lvItem.pszText = LPSTR_TEXTCALLBACKA; /*get text on a callback basis*/ + lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/ lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/ - return (-1==ListView_InsertItemA(This->hWndList, &lvItem))? FALSE: TRUE; + return (-1==ListView_InsertItemW(This->hWndList, &lvItem))? FALSE: TRUE; } /********************************************************** @@ -580,7 +582,7 @@ static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl) static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew ) { int nItem; - LVITEMA lvItem; + LVITEMW lvItem; TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew); @@ -589,14 +591,14 @@ static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCIT { lvItem.mask = LVIF_PARAM; /* only the pidl */ lvItem.iItem = nItem; - SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem); + SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem); SHFree((LPITEMIDLIST)lvItem.lParam); lvItem.mask = LVIF_PARAM; lvItem.iItem = nItem; lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */ - SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem); - SendMessageA(This->hWndList, LVM_UPDATE, nItem, 0); + SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem); + SendMessageW(This->hWndList, LVM_UPDATE, nItem, 0); return TRUE; /* FIXME: better handling */ } return FALSE; @@ -719,8 +721,8 @@ static LRESULT ShellView_OnCreate(IShellViewImpl * This) * ShellView_BuildFileMenu() */ static HMENU ShellView_BuildFileMenu(IShellViewImpl * This) -{ CHAR szText[MAX_PATH]; - MENUITEMINFOA mii; +{ WCHAR szText[MAX_PATH]; + MENUITEMINFOW mii; int nTools,i; HMENU hSubMenu; @@ -734,7 +736,7 @@ static HMENU ShellView_BuildFileMenu(IShellViewImpl * This) /*add the menu items*/ for(i = 0; i < nTools; i++) { - LoadStringA(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH); + LoadStringW(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH); ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); @@ -752,7 +754,7 @@ static HMENU ShellView_BuildFileMenu(IShellViewImpl * This) mii.fType = MFT_SEPARATOR; } /* tack This item onto the end of the menu */ - InsertMenuItemA(hSubMenu, (UINT)-1, TRUE, &mii); + InsertMenuItemW(hSubMenu, (UINT)-1, TRUE, &mii); } } TRACE("-- return (menu=%p)\n",hSubMenu); @@ -808,7 +810,7 @@ static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu) */ static UINT ShellView_GetSelections(IShellViewImpl * This) { - LVITEMA lvItem; + LVITEMW lvItem; UINT i = 0; SHFree(This->apidl); @@ -827,7 +829,7 @@ static UINT ShellView_GetSelections(IShellViewImpl * This) lvItem.iItem = 0; lvItem.iSubItem = 0; - while(ListView_GetItemA(This->hWndList, &lvItem) && (i < This->cidl)) + while(ListView_GetItemW(This->hWndList, &lvItem) && (i < This->cidl)) { if(lvItem.state & LVIS_SELECTED) { @@ -1257,7 +1259,7 @@ static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dw static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh) { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh; - NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh; + NMLVDISPINFOW *lpdi = (NMLVDISPINFOW *)lpnmh; LPITEMIDLIST pidl; TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code); @@ -1302,8 +1304,8 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This); break; - case HDN_ENDTRACKA: - TRACE("-- HDN_ENDTRACKA %p\n",This); + case HDN_ENDTRACKW: + TRACE("-- HDN_ENDTRACKW %p\n",This); /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0); nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/ break; @@ -1338,7 +1340,7 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn } This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID; - SendMessageA(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems); + SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems); break; case LVN_GETDISPINFOA: @@ -1354,13 +1356,15 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd); if (lpnmh->code == LVN_GETDISPINFOA) { - StrRetToStrNA( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL); - TRACE("-- text=%s\n",lpdi->item.pszText); + /* shouldn't happen */ + NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh; + StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL); + TRACE("-- text=%s\n",lpdiA->item.pszText); } else /* LVN_GETDISPINFOW */ { - StrRetToStrNW( ((NMLVDISPINFOW *)lpdi)->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL); - TRACE("-- text=%s\n",debugstr_w((WCHAR*)(lpdi->item.pszText))); + StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL); + TRACE("-- text=%s\n",debugstr_w(lpdi->item.pszText)); } } else @@ -1411,7 +1415,7 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn } break; - case LVN_BEGINLABELEDITA: + case LVN_BEGINLABELEDITW: { DWORD dwAttr = SFGAO_CANRENAME; pidl = (LPITEMIDLIST)lpdi->item.lParam; @@ -1426,30 +1430,27 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn return TRUE; } - case LVN_ENDLABELEDITA: + case LVN_ENDLABELEDITW: { TRACE("-- LVN_ENDLABELEDITA %p\n",This); if (lpdi->item.pszText) { HRESULT hr; - WCHAR wszNewName[MAX_PATH]; - LVITEMA lvItem; + LVITEMW lvItem; lvItem.iItem = lpdi->item.iItem; lvItem.iSubItem = 0; lvItem.mask = LVIF_PARAM; - SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem); + SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem); pidl = (LPITEMIDLIST)lpdi->item.lParam; - if (!MultiByteToWideChar( CP_ACP, 0, lpdi->item.pszText, -1, wszNewName, MAX_PATH )) - wszNewName[MAX_PATH-1] = 0; - hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, wszNewName, SHGDN_INFOLDER, &pidl); + hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl); if(SUCCEEDED(hr) && pidl) { lvItem.mask = LVIF_PARAM; lvItem.lParam = (LPARAM)pidl; - SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem); + SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem); return TRUE; } } @@ -1586,14 +1587,14 @@ static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, L static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) { IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); - LPCREATESTRUCTA lpcs; + LPCREATESTRUCTW lpcs; TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam); switch (uMessage) { case WM_NCCREATE: - lpcs = (LPCREATESTRUCTA)lParam; + lpcs = (LPCREATESTRUCTW)lParam; pThis = (IShellViewImpl*)(lpcs->lpCreateParams); SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis); pThis->hWnd = hWnd; /*set the window handle*/ @@ -1631,7 +1632,7 @@ static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wPara break; } - return DefWindowProcA (hWnd, uMessage, wParam, lParam); + return DefWindowProcW(hWnd, uMessage, wParam, lParam); } /********************************************************** * @@ -1847,7 +1848,7 @@ static HRESULT WINAPI IShellView_fnCreateViewWindow( { IShellViewImpl *This = (IShellViewImpl *)iface; - WNDCLASSA wc; + WNDCLASSW wc; *phWnd = 0; @@ -1871,7 +1872,7 @@ static HRESULT WINAPI IShellView_fnCreateViewWindow( } /*if our window class has not been registered, then do so*/ - if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc)) + if(!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc)) { ZeroMemory(&wc, sizeof(wc)); wc.style = CS_HREDRAW | CS_VREDRAW; @@ -1880,16 +1881,16 @@ static HRESULT WINAPI IShellView_fnCreateViewWindow( wc.cbWndExtra = 0; wc.hInstance = shell32_hInstance; wc.hIcon = 0; - wc.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW); + wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW); wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); wc.lpszMenuName = NULL; wc.lpszClassName = SV_CLASS_NAME; - if(!RegisterClassA(&wc)) + if(!RegisterClassW(&wc)) return E_FAIL; } - *phWnd = CreateWindowExA(0, + *phWnd = CreateWindowExW(0, SV_CLASS_NAME, NULL, WS_CHILD | WS_TABSTOP, @@ -1979,7 +1980,7 @@ static HRESULT WINAPI IShellView_fnSelectItem( if (i != -1) { - LVITEMA lvItem; + LVITEMW lvItem; if(uFlags & SVSI_ENSUREVISIBLE) SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0); @@ -1989,7 +1990,7 @@ static HRESULT WINAPI IShellView_fnSelectItem( lvItem.iItem = 0; lvItem.iSubItem = 0; - while(SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem)) + while(SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem)) { if (lvItem.iItem == i) { @@ -2006,7 +2007,7 @@ static HRESULT WINAPI IShellView_fnSelectItem( if (uFlags & SVSI_DESELECTOTHERS) lvItem.state &= ~LVIS_SELECTED; } - SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem); + SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem); lvItem.iItem++; } @@ -2212,7 +2213,7 @@ static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POIN DWORD *pdwEffect) { LVHITTESTINFO htinfo; - LVITEMA lvItem; + LVITEMW lvItem; LONG lResult; HRESULT hr; RECT clientRect; @@ -2270,7 +2271,7 @@ static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POIN lvItem.mask = LVIF_PARAM; lvItem.iItem = lResult; lvItem.iSubItem = 0; - SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem); + SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem); /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */ hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1, diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 8048412fae2..3e16dc3bf63 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -340,6 +340,98 @@ BOOL WINAPI GetLastInputInfo(PLASTINPUTINFO plii) } +/****************************************************************** +* GetRawInputDeviceList (USER32.@) +*/ +UINT WINAPI GetRawInputDeviceList(PRAWINPUTDEVICELIST pRawInputDeviceList, PUINT puiNumDevices, UINT cbSize) +{ + FIXME("(pRawInputDeviceList=%p, puiNumDevices=%p, cbSize=%d) stub!\n", pRawInputDeviceList, puiNumDevices, cbSize); + + if(pRawInputDeviceList) + memset(pRawInputDeviceList, 0, sizeof *pRawInputDeviceList); + *puiNumDevices = 0; + return 0; +} + + +/****************************************************************** +* RegisterRawInputDevices (USER32.@) +*/ +BOOL WINAPI RegisterRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize) +{ + FIXME("(pRawInputDevices=%p, uiNumDevices=%d, cbSize=%d) stub!\n", pRawInputDevices, uiNumDevices, cbSize); + + return TRUE; +} + + +/****************************************************************** +* GetRawInputData (USER32.@) +*/ +INT WINAPI GetRawInputData(HRAWINPUT hRawInput, UINT uiCommand, LPVOID pData, PUINT pcbSize, UINT cbSizeHeader) +{ + FIXME("(hRawInput=%p, uiCommand=%d, pData=%p, pcbSize=%p, cbSizeHeader=%d) stub!\n", + hRawInput, uiCommand, pData, pcbSize, cbSizeHeader); + + return 0; +} + + +/****************************************************************** +* GetRawInputBuffer (USER32.@) +*/ +UINT WINAPI GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader) +{ + FIXME("(pData=%p, pcbSize=%p, cbSizeHeader=%d) stub!\n", pData, pcbSize, cbSizeHeader); + + return 0; +} + + +/****************************************************************** +* GetRawInputDeviceInfoA (USER32.@) +*/ +UINT WINAPI GetRawInputDeviceInfoA(HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize) +{ + FIXME("(hDevice=%p, uiCommand=%d, pData=%p, pcbSize=%p) stub!\n", hDevice, uiCommand, pData, pcbSize); + + return 0; +} + + +/****************************************************************** +* GetRawInputDeviceInfoW (USER32.@) +*/ +UINT WINAPI GetRawInputDeviceInfoW(HANDLE hDevice, UINT uiCommand, LPVOID pData, PUINT pcbSize) +{ + FIXME("(hDevice=%p, uiCommand=%d, pData=%p, pcbSize=%p) stub!\n", hDevice, uiCommand, pData, pcbSize); + + return 0; +} + + +/****************************************************************** +* GetRegisteredRawInputDevices (USER32.@) +*/ +UINT WINAPI GetRegisteredRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, PUINT puiNumDevices, UINT cbSize) +{ + FIXME("(pRawInputDevices=%p, puiNumDevices=%p, cbSize=%d) stub!\n", pRawInputDevices, puiNumDevices, cbSize); + + return 0; +} + + +/****************************************************************** +* DefRawInputProc (USER32.@) +*/ +LRESULT WINAPI DefRawInputProc(PRAWINPUT *paRawInput, INT nInput, UINT cbSizeHeader) +{ + FIXME("(paRawInput=%p, nInput=%d, cbSizeHeader=%d) stub!\n", *paRawInput, nInput, cbSizeHeader); + + return 0; +} + + /********************************************************************** * AttachThreadInput (USER32.@) * diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index f373313d9e0..b3d9b69d59a 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -211,11 +211,13 @@ static const struct message WmSWP_ResizeNoZOrder[] = { { WM_GETTEXT, sent|defwinproc|optional }, { WM_ERASEBKGND, sent|optional }, /* FIXME: remove optional once Wine is fixed */ { WM_WINDOWPOSCHANGED, sent|wparam, /*SWP_NOZORDER|*/SWP_NOMOVE|SWP_NOCLIENTMOVE }, - { WM_SIZE, sent|defwinproc|wparam, 0 }, + { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, { WM_NCCALCSIZE, sent|wparam|optional, 1 }, /* Win9x doesn't send it */ { WM_NCPAINT, sent|optional }, /* Win9x doesn't send it */ { WM_GETTEXT, sent|defwinproc|optional }, /* Win9x doesn't send it */ { WM_ERASEBKGND, sent|optional }, /* Win9x doesn't send it */ + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 } }; @@ -224,57 +226,53 @@ static const struct message WmSwitchChild[] = { /* Switch MDI child */ { WM_MDIACTIVATE, sent },/* in the MDI client */ { WM_WINDOWPOSCHANGING, sent|wparam,SWP_NOSIZE|SWP_NOMOVE },/* in the 1st MDI child */ + { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_CHILDACTIVATE, sent },/* in the 1st MDI child */ /* Deactivate 2nd MDI child */ - { WM_NCACTIVATE, sent|defwinproc|optional },/* in the 2nd MDI child */ - { WM_MDIACTIVATE, sent|defwinproc|optional },/* in the 2nd MDI child */ - { WM_CREATE, hook }, + { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ + { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */ + { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, /* Preparing for maximize and maximaze the 1st MDI child */ - { WM_GETMINMAXINFO, sent|defwinproc|optional },/* in the 1st MDI child */ - { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_FRAMECHANGED|SWP_STATECHANGED },/* in the 1st MDI child */ - { WM_GETMINMAXINFO, sent|defwinproc|optional },/* in the 1st MDI child */ - { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 },/* in the 1st MDI child */ - { WM_CHILDACTIVATE, sent|defwinproc|optional },/* in the 1st MDI child */ - { WM_WINDOWPOSCHANGED, sent|defwinproc|optional },/* in the 1st MDI child */ - { WM_MOVE, sent|defwinproc|optional },/* in the 1st MDI child */ - { WM_SIZE, sent|defwinproc|optional },/* in the 1st MDI child */ + { WM_GETMINMAXINFO, sent|defwinproc }, /* in the 1st MDI child */ + { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, /* in the 1st MDI child */ + { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ + { WM_CHILDACTIVATE, sent|defwinproc }, /* in the 1st MDI child */ + { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 }, /* in the 1st MDI child */ + { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, /* in the 1st MDI child */ /* Lock redraw 2nd MDI child */ - { WM_SETREDRAW, sent|defwinproc|optional },/* in the 2nd MDI child */ - { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },/* in the 2nd MDI child */ - { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 },/* in the 2nd MDI child */ - { WM_WINDOWPOSCHANGED, sent|defwinproc|optional },/* in the 2nd MDI child */ - { WM_CREATE, hook }, + { WM_SETREDRAW, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ + { HCBT_MINMAX, hook|lparam, 0, SW_NORMALNA }, /* Restore 2nd MDI child */ - { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_SHOWWINDOW|SWP_STATECHANGED },/* in the 2nd MDI child */ - { WM_GETMINMAXINFO, sent|defwinproc|optional },/* in the 2nd MDI child */ - { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 },/* in the 2nd MDI child */ - { WM_WINDOWPOSCHANGED, sent|defwinproc|optional },/* in the 2nd MDI child */ - { WM_MOVE, sent|defwinproc|optional },/* in the 2nd MDI child */ - { WM_SIZE, sent|defwinproc|optional },/* in the 2nd MDI child */ + { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|0x8000 },/* in the 2nd MDI child */ + { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */ + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */ + { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|0x8000 }, /* in the 2nd MDI child */ + { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED }, /* in the 2nd MDI child */ + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 2nd MDI child */ /* Redraw 2nd MDI child */ - { WM_SETREDRAW, sent|defwinproc|optional },/* in the 2nd MDI child */ - { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_FRAMECHANGED|SWP_NOMOVE },/* in the 1st MDI child */ - { WM_NCCALCSIZE, sent|wparam|defwinproc|optional, 1 },/* in the 1st MDI child */ - { WM_WINDOWPOSCHANGED, sent|defwinproc|optional},/* in the 1st MDI child */ - { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_NOSIZE|SWP_FRAMECHANGED|SWP_NOMOVE },/* in the MDI frame */ - { WM_NCCALCSIZE, sent|wparam, 1 },/* in the MDI frame */ - { WM_WINDOWPOSCHANGED, sent},/* in the MDI frame */ - { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc|optional, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },/* in the 1st MDI child */ - { WM_NCACTIVATE, sent|defwinproc|optional },/* in the 1st MDI child */ - { WM_SETVISIBLE, hook }, - { WM_KILLFOCUS, sent|defwinproc|optional },/* in the 2nd MDI child */ - { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ - { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, + { WM_SETREDRAW, sent|wparam|defwinproc, 1 },/* in the 2nd MDI child */ + /* Redraw MDI frame */ + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE },/* in MDI frame */ + { WM_NCCALCSIZE, sent|wparam, 1 },/* in MDI frame */ + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE}, /* in MDI frame */ + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in MDI frame */ + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, /* in the 1st MDI child */ + { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE }, /* in the 1st MDI child */ + { WM_NCACTIVATE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ + { HCBT_SETFOCUS, hook }, + { WM_KILLFOCUS, sent|defwinproc }, /* in the 2nd MDI child */ + { WM_IME_SETCONTEXT, sent|wparam|defwinproc, 0 },/* in the 1st MDI child */ + { WM_IME_SETCONTEXT, sent|wparam, 1 }, /* in MDI client */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent },/* in the MDI client */ - { WM_SETVISIBLE, hook}, + { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent },/* in the MDI client */ - { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */ - { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, + { WM_IME_SETCONTEXT, sent|wparam, 0 }, /* in MDI client */ + { WM_IME_SETCONTEXT, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, - { WM_SETFOCUS, sent|defwinproc|optional },/* in the 1st MDI child */ - { WM_MDIACTIVATE, sent|defwinproc|optional },/* in the 1st MDI child */ - { WM_WINDOWPOSCHANGED, sent },/* in the 1st MDI child */ + { WM_SETFOCUS, sent|defwinproc }, /* in the 1st MDI child */ + { WM_MDIACTIVATE, sent|defwinproc },/* in the 1st MDI child */ + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, /* in the 1st MDI child */ { 0 } }; @@ -410,6 +408,7 @@ static const struct message WmShowMaxOverlappedSeq[] = { static const struct message WmShowMinOverlappedSeq[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, { HCBT_SETFOCUS, hook }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_KILLFOCUS, sent }, { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, @@ -417,12 +416,16 @@ static const struct message WmShowMinOverlappedSeq[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOCOPYBITS|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_STATECHANGED }, { WM_GETMINMAXINFO, sent|defwinproc }, { WM_NCCALCSIZE, sent|wparam, TRUE }, + { EVENT_OBJECT_REORDER, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCPAINT, sent }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_WINDOWPOSCHANGED, sent }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED }, { WM_NCCALCSIZE, sent|optional }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, { WM_NCACTIVATE, sent|wparam, 0 }, { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent }, @@ -468,6 +471,7 @@ static const struct message WmCreateMaxPopupSeq[] = { { 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 }, { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, @@ -477,9 +481,12 @@ static const struct message WmCreateMaxPopupSeq[] = { { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|0x8000 }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook }, + { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, @@ -488,6 +495,7 @@ static const struct message WmCreateMaxPopupSeq[] = { { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_SYNCPAINT, sent|wparam|optional, 4 }, { WM_NCPAINT, sent|wparam|optional, 1 }, @@ -501,6 +509,7 @@ static const struct message WmCreateInvisibleMaxPopupSeq[] = { { 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 }, { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, @@ -510,6 +519,7 @@ static const struct message WmCreateInvisibleMaxPopupSeq[] = { { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOREDRAW|0x8000 }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 } }; /* ShowWindow(SW_SHOWMAXIMIZED) for a resized not visible popup window */ @@ -518,7 +528,9 @@ static const struct message WmShowMaxPopupResizedSeq[] = { { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, { WM_NCCALCSIZE, sent|wparam, TRUE }, + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook }, + { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, @@ -527,6 +539,7 @@ static const struct message WmShowMaxPopupResizedSeq[] = { { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, @@ -534,6 +547,7 @@ static const struct message WmShowMaxPopupResizedSeq[] = { /* WinNT4.0 sends WM_MOVE */ { WM_MOVE, sent|defwinproc|optional }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 } }; /* ShowWindow(SW_SHOWMAXIMIZED) for a not visible popup window */ @@ -542,7 +556,9 @@ static const struct message WmShowMaxPopupSeq[] = { { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED }, { WM_NCCALCSIZE, sent|wparam, TRUE }, + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook }, + { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_ACTIVATEAPP, sent|wparam, 1 }, @@ -551,11 +567,13 @@ static const struct message WmShowMaxPopupSeq[] = { { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_SYNCPAINT, sent|wparam|optional, 4 }, { WM_NCPAINT, sent|wparam|optional, 1 }, { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 } }; /* CreateWindow(WS_VISIBLE) for popup window */ @@ -564,11 +582,14 @@ static const struct message WmCreatePopupSeq[] = { { 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_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { HCBT_ACTIVATE, hook }, + { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, { WM_NCPAINT, sent|wparam|optional, 1 }, @@ -579,6 +600,7 @@ static const struct message WmCreatePopupSeq[] = { { HCBT_SETFOCUS, hook }, { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, { WM_SYNCPAINT, sent|wparam|optional, 4 }, { WM_NCPAINT, sent|wparam|optional, 1 }, @@ -599,6 +621,7 @@ static const struct message WmShowVisMaxPopupSeq[] = { { WM_WINDOWPOSCHANGED, sent|wparam, SWP_FRAMECHANGED|0x8000 }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, { 0 } }; /* CreateWindow (for a child popup window, not initially visible) */ @@ -766,10 +789,12 @@ static const struct message WmShowChildInvisibleParentSeq_1[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|0x8000 }, { WM_NCCALCSIZE, sent|wparam, 1 }, + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCOPYBITS|0x8000 }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* FIXME: Wine creates an icon/title window while Windows doesn't */ { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, { WM_GETTEXT, sent|optional }, @@ -786,6 +811,7 @@ static const struct message WmShowChildInvisibleParentSeq_2[] = { { WM_GETMINMAXINFO, sent }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|0x8000 }, { WM_NCCALCSIZE, sent|wparam, 1 }, + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHILDACTIVATE, sent }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOREDRAW|SWP_NOCLIENTMOVE|0x8000 }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MAXIMIZED }, @@ -802,11 +828,13 @@ static const struct message WmShowChildInvisibleParentSeq_3[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINIMIZED }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 }, { WM_NCCALCSIZE, sent|wparam, 1 }, + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_CHILDACTIVATE, sent }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOREDRAW|SWP_NOCOPYBITS|0x8000 }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* FIXME: Wine creates an icon/title window while Windows doesn't */ { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, { WM_GETTEXT, sent|optional }, @@ -822,10 +850,12 @@ static const struct message WmShowChildInvisibleParentSeq_4[] = { { HCBT_MINMAX, hook|lparam, 0, SW_SHOWMINNOACTIVE }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|0x8000 }, { WM_NCCALCSIZE, sent|wparam, 1 }, + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOCOPYBITS|0x8000 }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc|wparam, SIZE_MINIMIZED }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 }, /* FIXME: Wine creates an icon/title window while Windows doesn't */ { WM_PARENTNOTIFY, sent|parent|wparam|optional, WM_CREATE }, { WM_GETTEXT, sent|optional }, @@ -2077,6 +2107,7 @@ static const struct message WmCreateMDIchildVisibleMaxSeq3[] = { { WM_SETFOCUS, sent|optional }, /* in MDI client */ { HCBT_SETFOCUS, hook }, /* in MDI client */ { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */ + { WM_IME_NOTIFY, sent|wparam|optional, 2 }, { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam|optional, OBJID_CLIENT, 0 }, { WM_SETFOCUS, sent|optional }, /* in MDI client */ { HCBT_SETFOCUS, hook|optional }, @@ -3191,6 +3222,60 @@ static void test_mdi_messages(void) flush_sequence(); /* end of test for maximized MDI children */ + SetFocus(0); + flush_sequence(); + trace("creating maximized visible MDI child window 1(Switch test)\n"); + mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", + WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, + 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, + mdi_client, 0, GetModuleHandleA(0), NULL); + assert(mdi_child); + ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window(Switch test)", TRUE); + ok(IsZoomed(mdi_child), "1st MDI child should be maximized(Switch test)\n"); + + ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); + ok(GetFocus() == mdi_child || /* win2k */ + GetFocus() == 0, /* win9x */ + "wrong focus window %p(Switch test)\n", GetFocus()); + + active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); + ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child); + ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); + flush_sequence(); + + trace("creating maximized visible MDI child window 2(Switch test)\n"); + mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", + WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, + 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, + mdi_client, 0, GetModuleHandleA(0), NULL); + assert(mdi_child2); + ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child window (Switch test)", TRUE); + + ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized(Switch test)\n"); + ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized(Switch test)\n"); + + ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); + ok(GetFocus() == mdi_child2, "wrong focus window %p(Switch test)\n", GetFocus()); + + active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); + ok(active_child == mdi_child2, "wrong active MDI child %p(Switch test)\n", active_child); + ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); + flush_sequence(); + + trace("Switch child window.\n"); + SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child, 0); + ok_sequence(WmSwitchChild, "Child did not switch correctly", TRUE); + trace("end of test for switch maximized MDI children\n"); + + SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); + flush_sequence(); + + SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0); + flush_sequence(); + + SetFocus(0); + flush_sequence(); + /* end of test for switch maximized MDI children */ mdi_cs.szClass = "MDI_child_Class"; mdi_cs.szTitle = "MDI child"; @@ -3263,58 +3348,6 @@ static void test_mdi_messages(void) /* end of test for maximization of MDI child with invisible parent */ - /* test for switch maximized MDI children */ - trace("creating maximized visible MDI child window 1(Switch test)\n"); - mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", - WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, - 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, - mdi_client, 0, GetModuleHandleA(0), NULL); - assert(mdi_child); - ok_sequence(WmCreateMDIchildVisibleMaxSeq1, "Create maximized visible 1st MDI child window(Switch test)", TRUE); - ok(IsZoomed(mdi_child), "1st MDI child should be maximized(Switch test)\n"); - - ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); - ok(GetFocus() == mdi_child || /* win2k */ - GetFocus() == 0, /* win9x */ - "wrong focus window %p(Switch test)\n", GetFocus()); - - active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); - ok(active_child == mdi_child, "wrong active MDI child %p(Switch test)\n", active_child); - ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); - flush_sequence(); - - trace("creating maximized visible MDI child window 2(Switch test)\n"); - mdi_child2 = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child", - WS_CHILD | WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE, - 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, - mdi_client, 0, GetModuleHandleA(0), NULL); - assert(mdi_child2); - ok_sequence(WmCreateMDIchildVisibleMaxSeq2, "Create maximized visible 2nd MDI child 2 window(Switch test)\n", TRUE); - ok(IsZoomed(mdi_child2), "2nd MDI child should be maximized(Switch test)\n"); - ok(!IsZoomed(mdi_child), "1st MDI child should NOT be maximized(Switch test)\n"); - - ok(GetActiveWindow() == mdi_frame, "wrong active window %p(Switch test)\n", GetActiveWindow()); - ok(GetFocus() == mdi_child2, "wrong focus window %p(Switch test)\n", GetFocus()); - - active_child = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, (LPARAM)&zoomed); - ok(active_child == mdi_child2, "wrong active MDI child %p(Switch test)\n", active_child); - ok(zoomed, "wrong zoomed state %d(Switch test)\n", zoomed); - flush_sequence(); - - trace("Switch child window.\n"); - SendMessageA(mdi_client, WM_MDIACTIVATE, (WPARAM)mdi_child, 0); - ok_sequence(WmSwitchChild,"Child not switch correctly\n",TRUE); - - trace("end of test for switch maximized MDI children\n"); - - SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); - flush_sequence(); - - SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child2, 0); - flush_sequence(); - - /* end of test for switch maximized MDI children */ - DestroyWindow(mdi_client); ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window", FALSE); @@ -7791,7 +7824,6 @@ static const struct message ml_edit_setfocus[] = { WM_SETFOCUS, sent|wparam, 0 }, { EVENT_OBJECT_CREATE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, - { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, { 0 } }; @@ -7828,6 +7860,7 @@ static const struct message sl_edit_lbutton_down[] = { WM_COMMAND, sent|parent|wparam, MAKEWPARAM(ID_EDIT, EN_SETFOCUS) }, { EVENT_SYSTEM_CAPTURESTART, winevent_hook|wparam|lparam, 0, 0 }, { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, + { WM_CTLCOLOREDIT, sent|parent|optional }, { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { 0 } @@ -8847,6 +8880,7 @@ static const struct message WmHide_3[] = { { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, { HCBT_SETFOCUS, hook }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { 0 } }; static const struct message WmShowMinimized_1[] = { @@ -8862,6 +8896,7 @@ static const struct message WmShowMinimized_1[] = { static const struct message WmMinimize_1[] = { { HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE }, { HCBT_SETFOCUS, hook|optional }, /* win2000 doesn't send it */ + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 }, { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|0x8000 }, { WM_MOVE, sent|defwinproc }, @@ -9135,7 +9170,9 @@ 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 */ + { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { WM_CTLCOLOREDIT, sent|optional }, /* XP */ + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, OBJID_CARET, 0 }, { 0 } }; /* Creation of a dialog */ @@ -9290,6 +9327,8 @@ static const struct message SetForegroundWindowSeq[] = { WM_ACTIVATE, sent|wparam, 0 }, { WM_ACTIVATEAPP, sent|wparam, 0 }, { WM_KILLFOCUS, sent }, + { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, + { WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 }, { 0 } }; diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index d62605346bd..417b93ef354 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -143,7 +143,7 @@ @ stdcall DefFrameProcW(long long long long long) @ stdcall DefMDIChildProcA(long long long long) @ stdcall DefMDIChildProcW(long long long long) -# @ stub DefRawInputProc +@ stdcall DefRawInputProc(ptr long long) @ stdcall DefWindowProcA(long long long long) @ stdcall DefWindowProcW(long long long long) @ stdcall DeferWindowPos(long long long long long long long long) @@ -341,13 +341,13 @@ @ stdcall GetPropA(long str) @ stdcall GetPropW(long wstr) @ stdcall GetQueueStatus(long) -# @ stub GetRawInputBuffer -# @ stub GetRawInputData -# @ stub GetRawInputDeviceInfoA -# @ stub GetRawInputDeviceInfoW -# @ stub GetRawInputDeviceList +@ stdcall GetRawInputBuffer(ptr ptr long) +@ stdcall GetRawInputData(ptr long ptr ptr long) +@ stdcall GetRawInputDeviceInfoA(ptr long ptr ptr) +@ stdcall GetRawInputDeviceInfoW(ptr long ptr ptr) +@ stdcall GetRawInputDeviceList(ptr ptr long) # @ stub GetReasonTitleFromReasonCode -# @ stub GetRegisteredRawInputDevices +@ stdcall GetRegisteredRawInputDevices(ptr ptr long) @ stdcall GetScrollBarInfo(long long ptr) @ stdcall GetScrollInfo(long long ptr) @ stdcall GetScrollPos(long long) @@ -562,7 +562,7 @@ @ stdcall RegisterLogonProcess(long long) # @ stub RegisterMessagePumpHook @ stub RegisterNetworkCapabilities -# @ stub RegisterRawInputDevices +@ stdcall RegisterRawInputDevices(ptr long long) @ stub RegisterServicesProcess @ stdcall RegisterShellHookWindow (long) @ stdcall RegisterSystemThread(long long) diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 7b851de41b4..2bb54483b2c 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -154,6 +154,7 @@ void shader_arb_load_constants( if (usePixelShader) { IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader; + IWineD3DPixelShaderImpl *psi = (IWineD3DPixelShaderImpl *) pshader; /* Load DirectX 9 float constants for pixel shader */ shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB, @@ -165,10 +166,31 @@ void shader_arb_load_constants( * number of the constant to load the matrix into. * The state manager takes care that this function is always called if the bump env matrix changes */ - IWineD3DPixelShaderImpl *psi = (IWineD3DPixelShaderImpl *) pshader; float *data = (float *) &stateBlock->textureState[(int) psi->needsbumpmat][WINED3DTSS_BUMPENVMAT00]; GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->bumpenvmatconst, data)); } + if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled && + !((IWineD3DPixelShaderImpl *) pshader)->srgb_mode_hardcoded) { + float comparison[4]; + float mul_low[4]; + + if(stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) { + comparison[0] = srgb_cmp; comparison[1] = srgb_cmp; + comparison[2] = srgb_cmp; comparison[3] = srgb_cmp; + + mul_low[0] = srgb_mul_low; mul_low[1] = srgb_mul_low; + mul_low[2] = srgb_mul_low; mul_low[3] = srgb_mul_low; + } else { + comparison[0] = 1.0 / 0.0; comparison[1] = 1.0 / 0.0; + comparison[2] = 1.0 / 0.0; comparison[3] = 1.0 / 0.0; + + mul_low[0] = 1.0; mul_low[1] = 1.0; + mul_low[2] = 1.0; mul_low[3] = 1.0; + } + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->srgb_cmp_const, comparison)); + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, psi->srgb_low_const, mul_low)); + checkGLcall("Load sRGB correction constants\n"); + } } } @@ -180,10 +202,12 @@ void shader_generate_arb_declarations( WineD3D_GL_Info* gl_info) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; DWORD i; char pshader = shader_is_pshader_version(This->baseShader.hex_version); unsigned max_constantsF = min(This->baseShader.limits.constant_float, (pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF))); + UINT extra_constants_needed = 0; /* Temporary Output register */ shader_addline(buffer, "TEMP TMP_OUT;\n"); @@ -220,6 +244,52 @@ void shader_generate_arb_declarations( } else { FIXME("No free constant found to load environemnt bump mapping matrix into the shader. texbem instruction will not apply bump mapping\n"); } + extra_constants_needed += 1; + } + if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE] && pshader) { + IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *) This; + /* If there are 2 constants left to use, use them to pass the sRGB correction values in. This way + * srgb write correction can be turned on and off dynamically without recompilation. Otherwise + * hardcode them. The drawback of hardcoding is that the shader needs recompilation to turn sRGB + * off again + */ + if(max_constantsF + extra_constants_needed + 1 < GL_LIMITS(pshader_constantsF) && FALSE) { + /* The idea is that if srgb is enabled, then disabled, the constant loading code + * can effectively disabling sRGB correction by passing 1.0 and INF as the multiplication + * and comparison constants. If it disables it that way, the shader won't be recompiled + * and the code will stay in, so sRGB writing can be turned on again by setting the + * constants from the spec + */ + ps_impl->srgb_mode_hardcoded = 0; + ps_impl->srgb_low_const = GL_LIMITS(pshader_constantsF) - extra_constants_needed; + ps_impl->srgb_cmp_const = GL_LIMITS(pshader_constantsF) - extra_constants_needed - 1; + shader_addline(buffer, "PARAM srgb_mul_low = program.env[%d];\n", ps_impl->srgb_low_const); + shader_addline(buffer, "PARAM srgb_comparison = program.env[%d];\n", ps_impl->srgb_cmp_const); + } else { + shader_addline(buffer, "PARAM srgb_mul_low = {%f, %f, %f, 1.0};\n", + srgb_mul_low, srgb_mul_low, srgb_mul_low); + shader_addline(buffer, "PARAM srgb_comparison = {%f, %f, %f, %f};\n", + srgb_cmp, srgb_cmp, srgb_cmp, srgb_cmp); + ps_impl->srgb_mode_hardcoded = 1; + } + /* These can be hardcoded, they do not cause any harm because no fragment will enter the high + * path if the comparison value is set to INF + */ + shader_addline(buffer, "PARAM srgb_pow = {%f, %f, %f, 1.0};\n", + srgb_pow, srgb_pow, srgb_pow); + shader_addline(buffer, "PARAM srgb_mul_hi = {%f, %f, %f, 1.0};\n", + srgb_mul_high, srgb_mul_high, srgb_mul_high); + shader_addline(buffer, "PARAM srgb_sub_hi = {%f, %f, %f, 0.0};\n", + srgb_sub_high, srgb_sub_high, srgb_sub_high); + ps_impl->srgb_enabled = 1; + } else if(pshader) { + IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *) This; + + /* Do not write any srgb fixup into the shader to save shader size and processing time. + * As a consequence, we can't toggle srgb write on without recompilation + */ + ps_impl->srgb_enabled = 0; + ps_impl->srgb_mode_hardcoded = 1; } /* Need to PARAM the environment parameters (constants) so we can use relative addressing */ @@ -246,10 +316,15 @@ static const char * const shift_tab[] = { "coefdiv.x" /* 15 (d2) */ }; -static void shader_arb_get_write_mask(const DWORD param, char *write_mask) { +static void shader_arb_get_write_mask(SHADER_OPCODE_ARG* arg, const DWORD param, char *write_mask) { + IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) arg->shader; char *ptr = write_mask; + char vshader = shader_is_vshader_version(This->baseShader.hex_version); - if ((param & WINED3DSP_WRITEMASK_ALL) != WINED3DSP_WRITEMASK_ALL) { + if(vshader && shader_get_regtype(param) == WINED3DSPR_ADDR) { + *ptr++ = '.'; + *ptr++ = 'x'; + } else if ((param & WINED3DSP_WRITEMASK_ALL) != WINED3DSP_WRITEMASK_ALL) { *ptr++ = '.'; if (param & WINED3DSP_WRITEMASK_0) *ptr++ = 'x'; if (param & WINED3DSP_WRITEMASK_1) *ptr++ = 'y'; @@ -402,7 +477,7 @@ static void vshader_program_add_param(SHADER_OPCODE_ARG *arg, const DWORD param, if (!is_input) { char write_mask[6]; - shader_arb_get_write_mask(param, write_mask); + shader_arb_get_write_mask(arg, param, write_mask); strcat(hwLine, write_mask); } else { char swizzle[6]; @@ -411,12 +486,7 @@ static void vshader_program_add_param(SHADER_OPCODE_ARG *arg, const DWORD param, } } -static void shader_hw_sample(SHADER_OPCODE_ARG* arg, DWORD sampler_idx, const char *dst_str, const char *coord_reg, BOOL projective) { - IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; - IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; - IWineD3DBaseTextureImpl *texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler_idx]; - WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info; - +static void shader_hw_sample(SHADER_OPCODE_ARG* arg, DWORD sampler_idx, const char *dst_str, const char *coord_reg, BOOL projected, BOOL bias) { SHADER_BUFFER* buffer = arg->buffer; DWORD sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK; const char *tex_type; @@ -443,24 +513,201 @@ static void shader_hw_sample(SHADER_OPCODE_ARG* arg, DWORD sampler_idx, const ch tex_type = ""; } - if (projective && deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED) { + if (bias) { + /* Shouldn't be possible, but let's check for it */ + if(projected) FIXME("Biased and Projected texture sampling\n"); + /* TXB takes the 4th component of the source vector automatically, as d3d. Nothing more to do */ + shader_addline(buffer, "TXB %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type); + } else if (projected) { shader_addline(buffer, "TXP %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type); } else { shader_addline(buffer, "TEX %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type); } +} - /* Signedness correction */ - if(!GL_SUPPORT(NV_TEXTURE_SHADER3) /* Provides signed formats */ && texture) { - WINED3DFORMAT format = texture->resource.format; +static void shader_arb_color_correction(SHADER_OPCODE_ARG* arg) { + IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) shader->baseShader.device; + WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info; + WINED3DFORMAT fmt; + WINED3DFORMAT conversion_group; + IWineD3DBaseTextureImpl *texture; + UINT i; + BOOL recorded = FALSE; + DWORD sampler_idx; + DWORD hex_version = shader->baseShader.hex_version; + char reg[256]; + char writemask[6]; - if((format == WINED3DFMT_V8U8 && !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) || - format == WINED3DFMT_Q8W8V8U8 || - format == WINED3DFMT_V16U16) { - shader_addline(buffer, "MAD %s, %s, coefmul.x, -one;\n", dst_str, dst_str); - } else if(format == WINED3DFMT_X8L8V8U8) { - shader_addline(buffer, "MAD %s.rg, %s, coefmul.x, -one;\n", dst_str, dst_str); + switch(arg->opcode->opcode) { + case WINED3DSIO_TEX: + if (hex_version < WINED3DPS_VERSION(2,0)) { + sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; + } else { + sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK; + } + break; + + case WINED3DSIO_TEXLDL: + FIXME("Add color fixup for vertex texture WINED3DSIO_TEXLDL\n"); + return; + + case WINED3DSIO_TEXDP3TEX: + case WINED3DSIO_TEXM3x3TEX: + case WINED3DSIO_TEXM3x3SPEC: + case WINED3DSIO_TEXM3x3VSPEC: + case WINED3DSIO_TEXBEM: + case WINED3DSIO_TEXREG2AR: + case WINED3DSIO_TEXREG2GB: + case WINED3DSIO_TEXREG2RGB: + sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; + break; + + default: + /* Not a texture sampling instruction, nothing to do */ + return; + }; + + texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler_idx]; + if(texture) { + fmt = texture->resource.format; + conversion_group = texture->baseTexture.shader_conversion_group; + } else { + fmt = WINED3DFMT_UNKNOWN; + conversion_group = WINED3DFMT_UNKNOWN; + } + + /* before doing anything, record the sampler with the format in the format conversion list, + * but check if it's not there already + */ + for(i = 0; i < shader->baseShader.num_sampled_samplers; i++) { + if(shader->baseShader.sampled_samplers[i] == sampler_idx) { + recorded = TRUE; } } + if(!recorded) { + shader->baseShader.sampled_samplers[shader->baseShader.num_sampled_samplers] = sampler_idx; + shader->baseShader.num_sampled_samplers++; + shader->baseShader.sampled_format[sampler_idx] = conversion_group; + } + + pshader_get_register_name(arg->dst, reg); + shader_arb_get_write_mask(arg, arg->dst, writemask); + if(strlen(writemask) == 0) strcpy(writemask, ".xyzw"); + + switch(fmt) { + case WINED3DFMT_V8U8: + case WINED3DFMT_V16U16: + if(GL_SUPPORT(NV_TEXTURE_SHADER) || + (GL_SUPPORT(ATI_ENVMAP_BUMPMAP) && fmt == WINED3DFMT_V8U8)) { +#if 0 + /* The 3rd channel returns 1.0 in d3d, but 0.0 in gl. Fix this while we're at it :-) + * disabled until an application that needs it is found because it causes unneeded + * shader recompilation in some game + */ + if(strlen(writemask) >= 4) { + shader_addline(arg->buffer, "MOV %s.%c, one.z;\n", reg, writemask[3]); + } +#endif + } else { + /* Correct the sign, but leave the blue as it is - it was loaded correctly already + * ARB shaders are a bit picky wrt writemasks and swizzles. If we're free to scale + * all registers, do so, this saves an instruction. + */ + if(strlen(writemask) >= 5) { + shader_addline(arg->buffer, "MAD %s, %s, coefmul.x, -one;\n", reg, reg); + } else if(strlen(writemask) >= 3) { + shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[1], + reg, writemask[1]); + shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[2], + reg, writemask[2]); + } else if(strlen(writemask) == 2) { + shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", reg, writemask[1], + reg, writemask[1]); + } + } + break; + + case WINED3DFMT_X8L8V8U8: + if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { + /* Red and blue are the signed channels, fix them up; Blue(=L) is correct already, + * and a(X) is always 1.0. Cannot do a full conversion due to L(blue) + */ + if(strlen(writemask) >= 3) { + shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[1], + reg, writemask[1]); + shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[2], + reg, writemask[2]); + } else if(strlen(writemask) == 2) { + shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[1], + reg, writemask[1]); + } + } + break; + + case WINED3DFMT_L6V5U5: + if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { + if(strlen(writemask) >= 4) { + /* Swap y and z (U and L), and do a sign conversion on x and the new y(V and U) */ + shader_addline(arg->buffer, "MOV TMP.g, %s.%c;\n", + reg, writemask[2]); + shader_addline(arg->buffer, "MAD %s.%c%c, %s.%c%c, coefmul.x, -one;\n", + reg, writemask[1], writemask[1], + reg, writemask[1], writemask[3]); + shader_addline(arg->buffer, "MOV %s.%c, TMP.g;\n", reg, + writemask[3]); + } else if(strlen(writemask) == 3) { + /* This is bad: We have VL, but we need VU */ + FIXME("2 components sampled from a converted L6V5U5 texture\n"); + } else { + shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[1], + reg, writemask[1]); + } + } + break; + + case WINED3DFMT_Q8W8V8U8: + if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { + /* Correct the sign in all channels */ + switch(strlen(writemask)) { + case 4: + shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[3], + reg, writemask[3]); + /* drop through */ + case 3: + shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[2], + reg, writemask[2]); + /* drop through */ + case 2: + shader_addline(arg->buffer, "MAD %s.%c, %s.%c, coefmul.x, -one;\n", + reg, writemask[1], + reg, writemask[1]); + break; + + /* Should not occur, since it's at minimum '.' and a letter */ + case 1: + ERR("Unexpected writemask: \"%s\"\n", writemask); + break; + + case 5: + default: + shader_addline(arg->buffer, "MAD %s, %s, coefmul.x, -one;\n", reg, reg); + } + } + break; + + /* stupid compiler */ + default: + break; + } } @@ -551,7 +798,7 @@ void pshader_hw_bem(SHADER_OPCODE_ARG* arg) { char dst_wmask[20]; pshader_get_register_name(arg->dst, dst_name); - shader_arb_get_write_mask(arg->dst, dst_wmask); + shader_arb_get_write_mask(arg, arg->dst, dst_wmask); strcat(dst_name, dst_wmask); pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0]); @@ -577,13 +824,14 @@ void pshader_hw_cnd(SHADER_OPCODE_ARG* arg) { char dst_wmask[20]; char dst_name[50]; char src_name[3][50]; + BOOL sat = (arg->dst & WINED3DSP_DSTMOD_MASK) & WINED3DSPDM_SATURATE; + DWORD shift = (arg->dst & WINED3DSP_DSTSHIFT_MASK) >> WINED3DSP_DSTSHIFT_SHIFT; /* FIXME: support output modifiers */ /* Handle output register */ pshader_get_register_name(arg->dst, dst_name); - shader_arb_get_write_mask(arg->dst, dst_wmask); - strcat(dst_name, dst_wmask); + shader_arb_get_write_mask(arg, arg->dst, dst_wmask); /* Generate input register names (with modifiers) */ pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src_name[0]); @@ -593,11 +841,14 @@ void pshader_hw_cnd(SHADER_OPCODE_ARG* arg) { /* The coissue flag changes the semantic of the cnd instruction in <= 1.3 shaders */ if (shader->baseShader.hex_version <= WINED3DPS_VERSION(1, 3) && arg->opcode_token & WINED3DSI_COISSUE) { - shader_addline(buffer, "MOV %s, %s;\n", dst_name, src_name[1]); + shader_addline(buffer, "MOV%s %s%s, %s;\n", sat ? "_SAT" : "", dst_name, dst_wmask, src_name[1]); } else { shader_addline(buffer, "ADD TMP, -%s, coefdiv.x;\n", src_name[0]); - shader_addline(buffer, "CMP %s, TMP, %s, %s;\n", dst_name, src_name[1], src_name[2]); + shader_addline(buffer, "CMP%s %s%s, TMP, %s, %s;\n", + sat ? "_SAT" : "", dst_name, dst_wmask, src_name[1], src_name[2]); } + if (shift != 0) + pshader_gen_output_modifier_line(buffer, FALSE, dst_wmask, shift, dst_name); } void pshader_hw_cmp(SHADER_OPCODE_ARG* arg) { @@ -611,7 +862,7 @@ void pshader_hw_cmp(SHADER_OPCODE_ARG* arg) { /* Handle output register */ pshader_get_register_name(arg->dst, dst_name); - shader_arb_get_write_mask(arg->dst, dst_wmask); + shader_arb_get_write_mask(arg, arg->dst, dst_wmask); strcat(dst_name, dst_wmask); /* Generate input register names (with modifiers) */ @@ -671,7 +922,7 @@ void pshader_hw_map2gl(SHADER_OPCODE_ARG* arg) { /* Handle output register */ pshader_get_register_name(dst, output_rname); strcpy(operands[0], output_rname); - shader_arb_get_write_mask(dst, output_wmask); + shader_arb_get_write_mask(arg, dst, output_wmask); strcat(operands[0], output_wmask); if (saturate && (shift == 0)) @@ -717,11 +968,13 @@ void pshader_hw_texkill(SHADER_OPCODE_ARG* arg) { void pshader_hw_tex(SHADER_OPCODE_ARG* arg) { IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; DWORD dst = arg->dst; DWORD* src = arg->src; SHADER_BUFFER* buffer = arg->buffer; DWORD hex_version = This->baseShader.hex_version; + BOOL projected = FALSE, bias = FALSE; char reg_dest[40]; char reg_coord[40]; @@ -746,7 +999,35 @@ void pshader_hw_tex(SHADER_OPCODE_ARG* arg) { else reg_sampler_code = src[1] & WINED3DSP_REGNUM_MASK; - shader_hw_sample(arg, reg_sampler_code, reg_dest, reg_coord, TRUE); + /* projection flag: + * 1.1, 1.2, 1.3: Use WINED3DTSS_TEXTURETRANSFORMFLAGS + * 1.4: Use WINED3DSPSM_DZ or WINED3DSPSM_DW on src[0] + * 2.0+: Use WINED3DSI_TEXLD_PROJECT on the opcode + */ + if(hex_version < WINED3DPS_VERSION(1,4)) { + DWORD flags = 0; + if(reg_sampler_code < MAX_TEXTURES) { + flags = deviceImpl->stateBlock->textureState[reg_sampler_code][WINED3DTSS_TEXTURETRANSFORMFLAGS]; + } + if (flags & WINED3DTTFF_PROJECTED) { + projected = TRUE; + } + } else if(hex_version < WINED3DPS_VERSION(2,0)) { + DWORD src_mod = arg->src[0] & WINED3DSP_SRCMOD_MASK; + if (src_mod == WINED3DSPSM_DZ) { + projected = TRUE; + } else if(src_mod == WINED3DSPSM_DW) { + projected = TRUE; + } + } else { + if(arg->opcode_token & WINED3DSI_TEXLD_PROJECT) { + projected = TRUE; + } + if(arg->opcode_token & WINED3DSI_TEXLD_BIAS) { + bias = TRUE; + } + } + shader_hw_sample(arg, reg_sampler_code, reg_dest, reg_coord, projected, bias); } void pshader_hw_texcoord(SHADER_OPCODE_ARG* arg) { @@ -757,7 +1038,7 @@ void pshader_hw_texcoord(SHADER_OPCODE_ARG* arg) { DWORD hex_version = This->baseShader.hex_version; char tmp[20]; - shader_arb_get_write_mask(dst, tmp); + shader_arb_get_write_mask(arg, dst, tmp); if (hex_version != WINED3DPS_VERSION(1,4)) { DWORD reg = dst & WINED3DSP_REGNUM_MASK; shader_addline(buffer, "MOV_SAT T%u%s, fragment.texcoord[%u];\n", reg, tmp, reg); @@ -773,6 +1054,9 @@ void pshader_hw_texcoord(SHADER_OPCODE_ARG* arg) { void pshader_hw_texreg2ar(SHADER_OPCODE_ARG* arg) { SHADER_BUFFER* buffer = arg->buffer; + IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; + DWORD flags; DWORD reg1 = arg->dst & WINED3DSP_REGNUM_MASK; DWORD reg2 = arg->src[0] & WINED3DSP_REGNUM_MASK; @@ -781,12 +1065,16 @@ void pshader_hw_texreg2ar(SHADER_OPCODE_ARG* arg) { sprintf(dst_str, "T%u", reg1); shader_addline(buffer, "MOV TMP.r, T%u.a;\n", reg2); shader_addline(buffer, "MOV TMP.g, T%u.r;\n", reg2); - shader_hw_sample(arg, reg1, dst_str, "TMP", TRUE); + flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; + shader_hw_sample(arg, reg1, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE); } void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) { SHADER_BUFFER* buffer = arg->buffer; + IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; + DWORD flags; DWORD reg1 = arg->dst & WINED3DSP_REGNUM_MASK; DWORD reg2 = arg->src[0] & WINED3DSP_REGNUM_MASK; @@ -795,7 +1083,8 @@ void pshader_hw_texreg2gb(SHADER_OPCODE_ARG* arg) { sprintf(dst_str, "T%u", reg1); shader_addline(buffer, "MOV TMP.r, T%u.g;\n", reg2); shader_addline(buffer, "MOV TMP.g, T%u.b;\n", reg2); - shader_hw_sample(arg, reg1, dst_str, "TMP", TRUE); + flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; + shader_hw_sample(arg, reg1, dst_str, "TMP", FALSE, FALSE); } void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) { @@ -833,10 +1122,16 @@ void pshader_hw_texbem(SHADER_OPCODE_ARG* arg) { shader_addline(buffer, "ADD TMP.rg, TMP, %s;\n", reg_coord); } - shader_hw_sample(arg, reg_dest_code, reg_coord, "TMP", FALSE); + shader_hw_sample(arg, reg_dest_code, reg_coord, "TMP", FALSE, FALSE); } else { + DWORD tf; + if(reg_dest_code < MAX_TEXTURES) { + tf = ((IWineD3DDeviceImpl*) This->baseShader.device)->stateBlock->textureState[reg_dest_code][WINED3DTSS_TEXTURETRANSFORMFLAGS]; + } else { + tf = 0; + } /* Without a bump matrix loaded, just sample with the unmodified coordinates */ - shader_hw_sample(arg, reg_dest_code, reg_coord, reg_coord, TRUE); + shader_hw_sample(arg, reg_dest_code, reg_coord, reg_coord, tf & WINED3DTTFF_PROJECTED, FALSE); } } @@ -852,6 +1147,9 @@ void pshader_hw_texm3x2pad(SHADER_OPCODE_ARG* arg) { void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG* arg) { + IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; + DWORD flags; DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK; SHADER_BUFFER* buffer = arg->buffer; char dst_str[8]; @@ -860,7 +1158,8 @@ void pshader_hw_texm3x2tex(SHADER_OPCODE_ARG* arg) { sprintf(dst_str, "T%u", reg); pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0_name); shader_addline(buffer, "DP3 TMP.y, T%u, %s;\n", reg, src0_name); - shader_hw_sample(arg, reg, dst_str, "TMP", TRUE); + flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; + shader_hw_sample(arg, reg, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE); } void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG* arg) { @@ -879,6 +1178,8 @@ void pshader_hw_texm3x3pad(SHADER_OPCODE_ARG* arg) { void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG* arg) { IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; + DWORD flags; DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK; SHADER_BUFFER* buffer = arg->buffer; SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state; @@ -890,13 +1191,16 @@ void pshader_hw_texm3x3tex(SHADER_OPCODE_ARG* arg) { /* Sample the texture using the calculated coordinates */ sprintf(dst_str, "T%u", reg); - shader_hw_sample(arg, reg, dst_str, "TMP", TRUE); + flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; + shader_hw_sample(arg, reg, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE); current_state->current_row = 0; } void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg) { IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; + DWORD flags; DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK; SHADER_BUFFER* buffer = arg->buffer; SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state; @@ -923,13 +1227,16 @@ void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg) { /* Sample the texture using the calculated coordinates */ sprintf(dst_str, "T%u", reg); - shader_hw_sample(arg, reg, dst_str, "TMP", TRUE); + flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; + shader_hw_sample(arg, reg, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE); current_state->current_row = 0; } void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg) { IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; + DWORD flags; DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK; DWORD reg3 = arg->src[1] & WINED3DSP_REGNUM_MASK; SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state; @@ -957,7 +1264,8 @@ void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg) { /* Sample the texture using the calculated coordinates */ sprintf(dst_str, "T%u", reg); - shader_hw_sample(arg, reg, dst_str, "TMP", TRUE); + flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0; + shader_hw_sample(arg, reg, dst_str, "TMP", flags & WINED3DTTFF_PROJECTED, FALSE); current_state->current_row = 0; } @@ -987,6 +1295,84 @@ void pshader_hw_texdepth(SHADER_OPCODE_ARG* arg) { shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n", dst_name, dst_name); } +/** Process the WINED3DSIO_TEXDP3TEX instruction in ARB: + * Take a 3-component dot product of the TexCoord[dstreg] and src, + * then perform a 1D texture lookup from stage dstregnum, place into dst. */ +void pshader_hw_texdp3tex(SHADER_OPCODE_ARG* arg) { + SHADER_BUFFER* buffer = arg->buffer; + DWORD sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; + char src0[50]; + char dst_str[8]; + + pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0); + shader_addline(buffer, "MOV TMP, 0.0;\n"); + shader_addline(buffer, "DP3 TMP.x, T%u, %s;\n", sampler_idx, src0); + + sprintf(dst_str, "T%u", sampler_idx); + shader_hw_sample(arg, sampler_idx, dst_str, "TMP", FALSE /* Only one coord, can't be projected */, FALSE); +} + +/** Process the WINED3DSIO_TEXDP3 instruction in ARB: + * Take a 3-component dot product of the TexCoord[dstreg] and src. */ +void pshader_hw_texdp3(SHADER_OPCODE_ARG* arg) { + char src0[50]; + char dst_str[50]; + char dst_mask[6]; + DWORD dstreg = arg->dst & WINED3DSP_REGNUM_MASK; + SHADER_BUFFER* buffer = arg->buffer; + + /* Handle output register */ + pshader_get_register_name(arg->dst, dst_str); + shader_arb_get_write_mask(arg, arg->dst, dst_mask); + + pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0); + shader_addline(buffer, "DP3 %s%s, T%u, %s;\n", dst_str, dst_mask, dstreg, src0); + + /* TODO: Handle output modifiers */ +} + +/** Process the WINED3DSIO_TEXM3X3 instruction in ARB + * Perform the 3rd row of a 3x3 matrix multiply */ +void pshader_hw_texm3x3(SHADER_OPCODE_ARG* arg) { + SHADER_BUFFER* buffer = arg->buffer; + char dst_str[50]; + char dst_mask[6]; + char src0[50]; + DWORD dst_reg = arg->dst & WINED3DSP_REGNUM_MASK; + + pshader_get_register_name(arg->dst, dst_str); + shader_arb_get_write_mask(arg, arg->dst, dst_mask); + + pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0); + shader_addline(buffer, "DP3 TMP.z, T%u, %s;\n", dst_reg, src0); + shader_addline(buffer, "MOV %s%s, TMP;\n", dst_str, dst_mask); + + /* TODO: Handle output modifiers */ +} + +/** Process the WINED3DSIO_TEXM3X2DEPTH instruction in ARB: + * Last row of a 3x2 matrix multiply, use the result to calculate the depth: + * Calculate tmp0.y = TexCoord[dstreg] . src.xyz; (tmp0.x has already been calculated) + * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y + */ +void pshader_hw_texm3x2depth(SHADER_OPCODE_ARG* arg) { + SHADER_BUFFER* buffer = arg->buffer; + DWORD dst_reg = arg->dst & WINED3DSP_REGNUM_MASK; + char src0[50]; + + pshader_gen_input_modifier_line(buffer, arg->src[0], 0, src0); + shader_addline(buffer, "DP3 TMP.y, T%u, %s;\n", dst_reg, src0); + + /* How to deal with the special case dst_name.g == 0? if r != 0, then + * the r * (1 / 0) will give infinity, which is clamped to 1.0, the correct + * result. But if r = 0.0, then 0 * inf = 0, which is incorrect. + */ + shader_addline(buffer, "RCP TMP.y, TMP.y;\n"); + shader_addline(buffer, "MUL TMP.x, TMP.x, TMP.y;\n"); + shader_addline(buffer, "MIN TMP.x, TMP.x, one.r;\n"); + shader_addline(buffer, "MAX result.depth, TMP.x, 0.0;\n"); +} + /** Handles transforming all WINED3DSIO_M?x? opcodes for Vertex shaders to ARB_vertex_program codes */ void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg) { @@ -1203,5 +1589,6 @@ const shader_backend_t arb_program_shader_backend = { &shader_arb_select, &shader_arb_select_depth_blt, &shader_arb_load_constants, - &shader_arb_cleanup + &shader_arb_cleanup, + &shader_arb_color_correction }; diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index d04a2e667a8..df9c3e53de5 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -718,6 +718,7 @@ void shader_generate_main( CONST DWORD* pFunction) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; /* To access shader backend callbacks */ const DWORD *pToken = pFunction; const SHADER_OPCODE *curOpcode = NULL; SHADER_HANDLER hw_fct = NULL; @@ -807,6 +808,9 @@ void shader_generate_main( /* Call appropriate function for output target */ hw_fct(&hw_arg); + /* Add color correction if needed */ + device->shader_backend->shader_color_correction(&hw_arg); + /* Process instruction modifiers for GLSL apps ( _sat, etc. ) */ if (This->baseShader.shader_mode == SHADER_GLSL) shader_glsl_add_instruction_modifiers(&hw_arg); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index d710a0d828b..c5a8aadb22b 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -99,7 +99,7 @@ static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3 *pp##type = NULL; \ return WINED3DERR_OUTOFVIDEOMEMORY; \ } \ - globalChangeGlRam(_size); \ + WineD3DAdapterChangeGLRam(This, _size); \ } \ object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \ if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \ @@ -846,6 +846,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U HRESULT hr; unsigned int pow2Width; unsigned int pow2Height; + const GlPixelFormatDesc *glDesc; + getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc); TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage); @@ -928,6 +930,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U tmpW = max(1, tmpW >> 1); tmpH = max(1, tmpH >> 1); } + object->baseTexture.shader_conversion_group = glDesc->conversion_group; TRACE("(%p) : Created texture %p\n", This, object); return WINED3D_OK; @@ -947,6 +950,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa UINT tmpW; UINT tmpH; UINT tmpD; + const GlPixelFormatDesc *glDesc; + getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc); /* TODO: It should only be possible to create textures for formats that are reported as supported */ @@ -1017,6 +1022,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa tmpH = max(1, tmpH >> 1); tmpD = max(1, tmpD >> 1); } + object->baseTexture.shader_conversion_group = glDesc->conversion_group; *ppVolumeTexture = (IWineD3DVolumeTexture *) object; TRACE("(%p) : Created volume texture %p\n", This, object); @@ -1066,6 +1072,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface UINT tmpW; HRESULT hr; unsigned int pow2EdgeLength = EdgeLength; + const GlPixelFormatDesc *glDesc; + getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc); /* TODO: It should only be possible to create textures for formats that are reported as supported */ @@ -1149,6 +1157,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface } tmpW = max(1, tmpW >> 1); } + object->baseTexture.shader_conversion_group = glDesc->conversion_group; TRACE("(%p) : Created Cube Texture %p\n", This, object); *ppCubeTexture = (IWineD3DCubeTexture *) object; @@ -2286,24 +2295,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWin } static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) { - /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBOs (or whatever) - * into the video ram as possible and seeing how many fit - * you can also get the correct initial value from nvidia and ATI's driver via X - * texture memory is video memory + AGP memory - *******************/ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - static BOOL showfixmes = TRUE; - if (showfixmes) { - FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This, - (wined3d_settings.emulated_textureram/(1024*1024)), - ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024))); - showfixmes = FALSE; - } + TRACE("(%p) : simulating %dMB, returning %dMB left\n", This, - (wined3d_settings.emulated_textureram/(1024*1024)), - ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024))); + (This->adapter->TextureRam/(1024*1024)), + ((This->adapter->TextureRam - This->adapter->UsedTextureRam) / (1024*1024))); /* return simulated texture memory left */ - return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram); + return (This->adapter->TextureRam - This->adapter->UsedTextureRam); } diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 747caae37c1..ce72d88d693 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -277,6 +277,14 @@ static BOOL WineD3D_CreateFakeGLContext(void) { return FALSE; } +/* Adjust the amount of used texture memory */ +long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){ + UINT Adapter = D3DDevice->adapterNo; + + Adapters[Adapter].UsedTextureRam += glram; + TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam); + return Adapters[Adapter].UsedTextureRam; +} /********************************************************** * IUnknown parts follows @@ -1034,16 +1042,11 @@ BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) { } TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card); - /* Unless VideoMemorySize is set in the registry, the default is 0 - * TODO: put emulated_textureram in the device */ - if(wined3d_settings.emulated_textureram == 0) { - /* If we have an estimate use it, else default to 64MB */ - if(vidmem) - wined3d_settings.emulated_textureram = vidmem*1024*1024; /* convert from MBs to bytes */ - else - wined3d_settings.emulated_textureram = WINE_DEFAULT_VIDMEM; - TRACE("Emulating %d MB of texture memory\n", wined3d_settings.emulated_textureram); - } + /* If we have an estimate use it, else default to 64MB; */ + if(vidmem) + gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */ + else + gl_info->vidmem = WINE_DEFAULT_VIDMEM; /* Load all the lookup tables TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */ @@ -2743,6 +2746,14 @@ BOOL InitAdapters(void) { Adapters[0].driver = "Display"; Adapters[0].description = "Direct3D HAL"; + /* Use the VideoRamSize registry setting when set */ + if(wined3d_settings.emulated_textureram) + Adapters[0].TextureRam = wined3d_settings.emulated_textureram; + else + Adapters[0].TextureRam = Adapters[0].gl_info.vidmem; + Adapters[0].UsedTextureRam = 0; + TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam); + /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */ DisplayDevice.cb = sizeof(DisplayDevice); EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index b3ea71ecfbb..57685a3c272 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -443,6 +443,31 @@ void shader_glsl_load_constants( GL_EXTCALL(glUniform1fvARB(pos, 1, offset)); checkGLcall("glUniform1fvARB"); } + } else if(((IWineD3DPixelShaderImpl *) pshader)->srgb_enabled && + !((IWineD3DPixelShaderImpl *) pshader)->srgb_mode_hardcoded) { + float comparison[4]; + float mul_low[4]; + + if(stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) { + comparison[0] = srgb_cmp; comparison[1] = srgb_cmp; + comparison[2] = srgb_cmp; comparison[3] = srgb_cmp; + + mul_low[0] = srgb_mul_low; mul_low[1] = srgb_mul_low; + mul_low[2] = srgb_mul_low; mul_low[3] = srgb_mul_low; + } else { + comparison[0] = 1.0 / 0.0; comparison[1] = 1.0 / 0.0; + comparison[2] = 1.0 / 0.0; comparison[3] = 1.0 / 0.0; + + mul_low[0] = 1.0; mul_low[1] = 1.0; + mul_low[2] = 1.0; mul_low[3] = 1.0; + } + + pos = GL_EXTCALL(glGetUniformLocationARB(programId, "srgb_comparison")); + checkGLcall("glGetUniformLocationARB"); + GL_EXTCALL(glUniform4fvARB(pos, 1, comparison)); + pos = GL_EXTCALL(glGetUniformLocationARB(programId, "srgb_mul_low")); + checkGLcall("glGetUniformLocationARB"); + GL_EXTCALL(glUniform4fvARB(pos, 1, mul_low)); } } } @@ -455,7 +480,9 @@ void shader_generate_glsl_declarations( WineD3D_GL_Info* gl_info) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; + IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device; int i; + unsigned int extra_constants_needed = 0; /* There are some minor differences between pixel and vertex shaders */ char pshader = shader_is_pshader_version(This->baseShader.hex_version); @@ -480,13 +507,42 @@ void shader_generate_glsl_declarations( if (This->baseShader.limits.constant_bool > 0) shader_addline(buffer, "uniform bool %cB[%u];\n", prefix, This->baseShader.limits.constant_bool); - if(!pshader) + if(!pshader) { shader_addline(buffer, "uniform vec4 posFixup;\n"); - else if(reg_maps->bumpmat != -1) { - shader_addline(buffer, "uniform mat2 bumpenvmat;\n"); - if(reg_maps->luminanceparams) { - shader_addline(buffer, "uniform float luminancescale;\n"); - shader_addline(buffer, "uniform float luminanceoffset;\n"); + } else { + IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *) This; + + if(reg_maps->bumpmat != -1) { + shader_addline(buffer, "uniform mat2 bumpenvmat;\n"); + if(reg_maps->luminanceparams) { + shader_addline(buffer, "uniform float luminancescale;\n"); + shader_addline(buffer, "uniform float luminanceoffset;\n"); + extra_constants_needed++; + } + extra_constants_needed++; + } + + if(device->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE]) { + ps_impl->srgb_enabled = 1; + if(This->baseShader.limits.constant_float + extra_constants_needed + 1 < GL_LIMITS(pshader_constantsF)) { + shader_addline(buffer, "uniform vec4 srgb_mul_low;\n"); + shader_addline(buffer, "uniform vec4 srgb_comparison;\n"); + ps_impl->srgb_mode_hardcoded = 0; + } else { + ps_impl->srgb_mode_hardcoded = 1; + shader_addline(buffer, "const vec4 srgb_mul_low = {%f, %f, %f, %f};\n", + srgb_mul_low, srgb_mul_low, srgb_mul_low, srgb_mul_low); + shader_addline(buffer, "const vec4 srgb_comparison = {%f, %f, %f, %f};\n", + srgb_cmp, srgb_cmp, srgb_cmp, srgb_cmp); + } + } else { + IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *) This; + + /* Do not write any srgb fixup into the shader to save shader size and processing time. + * As a consequence, we can't toggle srgb write on without recompilation + */ + ps_impl->srgb_enabled = 0; + ps_impl->srgb_mode_hardcoded = 1; } } @@ -969,6 +1025,165 @@ static void shader_glsl_get_sample_function(DWORD sampler_type, BOOL projected, } } +static void shader_glsl_color_correction(SHADER_OPCODE_ARG* arg) { + IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) shader->baseShader.device; + WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info; + glsl_dst_param_t dst_param; + glsl_dst_param_t dst_param2; + WINED3DFORMAT fmt; + WINED3DFORMAT conversion_group; + IWineD3DBaseTextureImpl *texture; + DWORD mask, mask_size; + UINT i; + BOOL recorded = FALSE; + DWORD sampler_idx; + DWORD hex_version = shader->baseShader.hex_version; + + switch(arg->opcode->opcode) { + case WINED3DSIO_TEX: + if (hex_version < WINED3DPS_VERSION(2,0)) { + sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; + } else { + sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK; + } + break; + + case WINED3DSIO_TEXLDL: + FIXME("Add color fixup for vertex texture WINED3DSIO_TEXLDL\n"); + return; + + case WINED3DSIO_TEXDP3TEX: + case WINED3DSIO_TEXM3x3TEX: + case WINED3DSIO_TEXM3x3SPEC: + case WINED3DSIO_TEXM3x3VSPEC: + case WINED3DSIO_TEXBEM: + case WINED3DSIO_TEXREG2AR: + case WINED3DSIO_TEXREG2GB: + case WINED3DSIO_TEXREG2RGB: + sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; + break; + + default: + /* Not a texture sampling instruction, nothing to do */ + return; + }; + + texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler_idx]; + if(texture) { + fmt = texture->resource.format; + conversion_group = texture->baseTexture.shader_conversion_group; + } else { + fmt = WINED3DFMT_UNKNOWN; + conversion_group = WINED3DFMT_UNKNOWN; + } + + /* before doing anything, record the sampler with the format in the format conversion list, + * but check if it's not there already + */ + for(i = 0; i < shader->baseShader.num_sampled_samplers; i++) { + if(shader->baseShader.sampled_samplers[i] == sampler_idx) { + recorded = TRUE; + break; + } + } + if(!recorded) { + shader->baseShader.sampled_samplers[shader->baseShader.num_sampled_samplers] = sampler_idx; + shader->baseShader.num_sampled_samplers++; + shader->baseShader.sampled_format[sampler_idx] = conversion_group; + } + + switch(fmt) { + case WINED3DFMT_V8U8: + case WINED3DFMT_V16U16: + if(GL_SUPPORT(NV_TEXTURE_SHADER) || + (GL_SUPPORT(ATI_ENVMAP_BUMPMAP) && fmt == WINED3DFMT_V8U8)) { + /* The 3rd channel returns 1.0 in d3d, but 0.0 in gl. Fix this while we're at it :-) */ + mask = shader_glsl_add_dst_param(arg, arg->dst, WINED3DSP_WRITEMASK_2, &dst_param); + mask_size = shader_glsl_get_write_mask_size(mask); + if(mask_size >= 3) { + shader_addline(arg->buffer, "%s.%c = 1.0;\n", dst_param.reg_name, dst_param.mask_str[3]); + } + } else { + /* Correct the sign, but leave the blue as it is - it was loaded correctly already */ + mask = shader_glsl_add_dst_param(arg, arg->dst, + WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, + &dst_param); + mask_size = shader_glsl_get_write_mask_size(mask); + if(mask_size >= 2) { + shader_addline(arg->buffer, "%s.%c%c = %s.%c%c * 2.0 - 1.0;\n", + dst_param.reg_name, dst_param.mask_str[1], dst_param.mask_str[2], + dst_param.reg_name, dst_param.mask_str[1], dst_param.mask_str[2]); + } else if(mask_size == 1) { + shader_addline(arg->buffer, "%s.%c = %s.%c * 2.0 - 1.0;\n", dst_param.reg_name, dst_param.mask_str[1], + dst_param.reg_name, dst_param.mask_str[1]); + } + } + break; + + case WINED3DFMT_X8L8V8U8: + if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { + /* Red and blue are the signed channels, fix them up; Blue(=L) is correct already, + * and a(X) is always 1.0 + */ + mask = shader_glsl_add_dst_param(arg, arg->dst, WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &dst_param); + mask_size = shader_glsl_get_write_mask_size(mask); + if(mask_size >= 2) { + shader_addline(arg->buffer, "%s.%c%c = %s.%c%c * 2.0 - 1.0;\n", + dst_param.reg_name, dst_param.mask_str[1], dst_param.mask_str[2], + dst_param.reg_name, dst_param.mask_str[1], dst_param.mask_str[2]); + } else if(mask_size == 1) { + shader_addline(arg->buffer, "%s.%c = %s.%c * 2.0 - 1.0;\n", + dst_param.reg_name, dst_param.mask_str[1], + dst_param.reg_name, dst_param.mask_str[1]); + } + } + break; + + case WINED3DFMT_L6V5U5: + if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { + mask = shader_glsl_add_dst_param(arg, arg->dst, WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &dst_param); + mask_size = shader_glsl_get_write_mask_size(mask); + shader_glsl_add_dst_param(arg, arg->dst, WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_2, &dst_param2); + if(mask_size >= 3) { + /* Swap y and z (U and L), and do a sign conversion on x and the new y(V and U) */ + shader_addline(arg->buffer, "tmp0.g = %s.%c;\n", + dst_param.reg_name, dst_param.mask_str[2]); + shader_addline(arg->buffer, "%s.%c%c = %s.%c%c * 2.0 - 1.0;\n", + dst_param.reg_name, dst_param.mask_str[2], dst_param.mask_str[1], + dst_param2.reg_name, dst_param.mask_str[1], dst_param.mask_str[3]); + shader_addline(arg->buffer, "%s.%c = tmp0.g;\n", dst_param.reg_name, + dst_param.mask_str[3]); + } else if(mask_size == 2) { + /* This is bad: We have VL, but we need VU */ + FIXME("2 components sampled from a converted L6V5U5 texture\n"); + } else { + shader_addline(arg->buffer, "%s.%c = %s.%c * 2.0 - 1.0;\n", + dst_param.reg_name, dst_param.mask_str[1], + dst_param2.reg_name, dst_param.mask_str[1]); + } + } + break; + + case WINED3DFMT_Q8W8V8U8: + if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { + /* Correct the sign in all channels. The writemask just applies as-is, no + * need for checking the mask size + */ + shader_glsl_add_dst_param(arg, arg->dst, + WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | + WINED3DSP_WRITEMASK_2 | WINED3DSP_WRITEMASK_3, + &dst_param); + shader_addline(arg->buffer, "%s%s = %s%s * 2.0 - 1.0;\n", dst_param.reg_name, dst_param.mask_str, + dst_param.reg_name, dst_param.mask_str); + } + break; + + /* stupid compiler */ + default: + break; + } +} /***************************************************************************** * @@ -1593,6 +1808,7 @@ void shader_glsl_callnz(SHADER_OPCODE_ARG* arg) { ********************************************/ void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) { IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader; + IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; DWORD hex_version = This->baseShader.hex_version; char dst_swizzle[6]; glsl_sample_function_t sample_function; @@ -1607,7 +1823,6 @@ void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) { /* 1.0-1.4: Use destination register as sampler source. * 2.0+: Use provided sampler source. */ if (hex_version < WINED3DPS_VERSION(1,4)) { - IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; DWORD flags; sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; @@ -2083,6 +2298,7 @@ void pshader_glsl_bem(SHADER_OPCODE_ARG* arg) { /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */ void pshader_glsl_texreg2ar(SHADER_OPCODE_ARG* arg) { + glsl_src_param_t src0_param; DWORD sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK; char dst_mask[6]; @@ -2483,5 +2699,6 @@ const shader_backend_t glsl_shader_backend = { &shader_glsl_select, &shader_glsl_select_depth_blt, &shader_glsl_load_constants, - &shader_glsl_cleanup + &shader_glsl_cleanup, + &shader_glsl_color_correction }; diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 0bcbdce55a5..24c025d6906 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -67,6 +67,22 @@ static ULONG WINAPI IWineD3DPixelShaderImpl_AddRef(IWineD3DPixelShader *iface) return InterlockedIncrement(&This->ref); } +static void destroy_glsl_pshader(IWineD3DPixelShaderImpl *This) { + struct list *linked_programs = &This->baseShader.linked_programs; + + TRACE("Deleting linked programs\n"); + if (linked_programs->next) { + struct glsl_shader_prog_link *entry, *entry2; + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, pshader_entry) { + delete_glsl_program_entry(This->baseShader.device, entry); + } + } + + TRACE("Deleting shader object %u\n", This->baseShader.prgId); + GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId)); + checkGLcall("glDeleteObjectARB"); +} + static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface) { IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; ULONG ref; @@ -74,19 +90,7 @@ static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface) ref = InterlockedDecrement(&This->ref); if (ref == 0) { if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) { - struct list *linked_programs = &This->baseShader.linked_programs; - - TRACE("Deleting linked programs\n"); - if (linked_programs->next) { - struct glsl_shader_prog_link *entry, *entry2; - LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, pshader_entry) { - delete_glsl_program_entry(This->baseShader.device, entry); - } - } - - TRACE("Deleting shader object %u\n", This->baseShader.prgId); - GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId)); - checkGLcall("glDeleteObjectARB"); + destroy_glsl_pshader(This); } shader_delete_constant_list(&This->baseShader.constantsF); shader_delete_constant_list(&This->baseShader.constantsB); @@ -234,10 +238,10 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = { {WINED3DSIO_TEXM3x3SPEC, "texm3x3spec", "undefined", 1, 3, pshader_hw_texm3x3spec, pshader_glsl_texm3x3spec, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)}, {WINED3DSIO_TEXM3x3VSPEC, "texm3x3vspec", "undefined", 1, 2, pshader_hw_texm3x3vspec, pshader_glsl_texm3x3vspec, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)}, {WINED3DSIO_TEXM3x3TEX, "texm3x3tex", "undefined", 1, 2, pshader_hw_texm3x3tex, pshader_glsl_texm3x3tex, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,3)}, - {WINED3DSIO_TEXDP3TEX, "texdp3tex", GLNAME_REQUIRE_GLSL, 1, 2, NULL, pshader_glsl_texdp3tex, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)}, - {WINED3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 1, 2, NULL, pshader_glsl_texm3x2depth, WINED3DPS_VERSION(1,3), WINED3DPS_VERSION(1,3)}, - {WINED3DSIO_TEXDP3, "texdp3", GLNAME_REQUIRE_GLSL, 1, 2, NULL, pshader_glsl_texdp3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)}, - {WINED3DSIO_TEXM3x3, "texm3x3", GLNAME_REQUIRE_GLSL, 1, 2, NULL, pshader_glsl_texm3x3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)}, + {WINED3DSIO_TEXDP3TEX, "texdp3tex", NULL, 1, 2, pshader_hw_texdp3tex, pshader_glsl_texdp3tex, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)}, + {WINED3DSIO_TEXM3x2DEPTH, "texm3x2depth", GLNAME_REQUIRE_GLSL, 1, 2, pshader_hw_texm3x2depth, pshader_glsl_texm3x2depth, WINED3DPS_VERSION(1,3), WINED3DPS_VERSION(1,3)}, + {WINED3DSIO_TEXDP3, "texdp3", NULL, 1, 2, pshader_hw_texdp3, pshader_glsl_texdp3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)}, + {WINED3DSIO_TEXM3x3, "texm3x3", NULL, 1, 2, pshader_hw_texm3x3, pshader_glsl_texm3x3, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(1,3)}, {WINED3DSIO_TEXDEPTH, "texdepth", NULL, 1, 1, pshader_hw_texdepth, pshader_glsl_texdepth, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)}, {WINED3DSIO_BEM, "bem", "undefined", 1, 3, pshader_hw_bem, pshader_glsl_bem, WINED3DPS_VERSION(1,4), WINED3DPS_VERSION(1,4)}, {WINED3DSIO_DSX, "dsx", NULL, 1, 2, NULL, shader_glsl_map2gl, WINED3DPS_VERSION(2,1), -1}, @@ -395,6 +399,23 @@ static inline VOID IWineD3DPixelShaderImpl_GenerateShader( else shader_addline(&buffer, "gl_FragColor.xyz = mix(gl_Fog.color.xyz, gl_FragColor.xyz, Fog);\n"); } + if(This->srgb_enabled) { + const char *fragcolor; + + if(GL_SUPPORT(ARB_DRAW_BUFFERS)) { + fragcolor = "gl_FragData[0]"; + } else { + fragcolor = "gl_FragColor"; + } + shader_addline(&buffer, "tmp0.xyz = pow(%s.xyz, vec3(%f, %f, %f)) * vec3(%f, %f, %f) - vec3(%f, %f, %f);\n", + fragcolor, srgb_pow, srgb_pow, srgb_pow, srgb_mul_high, srgb_mul_high, srgb_mul_high, + srgb_sub_high, srgb_sub_high, srgb_sub_high); + shader_addline(&buffer, "tmp1.xyz = %s.xyz * srgb_mul_low.xyz;\n", fragcolor); + shader_addline(&buffer, "%s.x = %s.x < srgb_comparison.x ? tmp1.x : tmp0.x;\n", fragcolor, fragcolor); + shader_addline(&buffer, "%s.y = %s.y < srgb_comparison.y ? tmp1.y : tmp0.y;\n", fragcolor, fragcolor); + shader_addline(&buffer, "%s.z = %s.z < srgb_comparison.z ? tmp1.z : tmp0.z;\n", fragcolor, fragcolor); + shader_addline(&buffer, "%s = clamp(%s, 0.0, 1.0);\n", fragcolor, fragcolor); + } shader_addline(&buffer, "}\n"); @@ -436,12 +457,41 @@ static inline VOID IWineD3DPixelShaderImpl_GenerateShader( * -1/(e-s) and e/(e-s) respectively. */ shader_addline(&buffer, "MAD_SAT TMP_FOG, fragment.fogcoord, state.fog.params.y, state.fog.params.z;\n"); - if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) { - shader_addline(&buffer, "LRP result.color.rgb, TMP_FOG.x, R0, state.fog.color;\n"); - shader_addline(&buffer, "MOV result.color.a, R0.a;\n"); + + if(This->srgb_enabled) { + if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) { + shader_addline(&buffer, "LRP TMP_COLOR.rgb, TMP_FOG.x, R0, state.fog.color;\n"); + shader_addline(&buffer, "MOV result.color.a, R0.a;\n"); + } else { + shader_addline(&buffer, "LRP TMP_COLOR.rgb, TMP_FOG.x, TMP_COLOR, state.fog.color;\n"); + shader_addline(&buffer, "MOV result.color.a, TMP_COLOR.a;\n"); + } + /* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */ + + /* Calculate the > 0.0031308 case */ + shader_addline(&buffer, "POW TMP.x, TMP_COLOR.x, srgb_pow.x;\n"); + shader_addline(&buffer, "POW TMP.y, TMP_COLOR.y, srgb_pow.y;\n"); + shader_addline(&buffer, "POW TMP.z, TMP_COLOR.z, srgb_pow.z;\n"); + shader_addline(&buffer, "MUL TMP, TMP, srgb_mul_hi;\n"); + shader_addline(&buffer, "SUB TMP, TMP, srgb_sub_hi;\n"); + /* Calculate the < case */ + shader_addline(&buffer, "MUL TMP2, srgb_mul_low, TMP_COLOR;\n"); + /* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */ + shader_addline(&buffer, "SLT TA, srgb_comparison, TMP_COLOR;\n"); + shader_addline(&buffer, "SGE TB, srgb_comparison, TMP_COLOR;\n"); + /* Store the components > 0.0031308 in the destination */ + shader_addline(&buffer, "MUL TMP_COLOR, TMP, TA;\n"); + /* Add the components that are < 0.0031308 */ + shader_addline(&buffer, "MAD result.color.xyz, TMP2, TB, TMP_COLOR;\n"); + /* [0.0;1.0] clamping. Not needed, this is done implicitly */ } else { - shader_addline(&buffer, "LRP result.color.rgb, TMP_FOG.x, TMP_COLOR, state.fog.color;\n"); - shader_addline(&buffer, "MOV result.color.a, TMP_COLOR.a;\n"); + if (This->baseShader.hex_version < WINED3DPS_VERSION(2,0)) { + shader_addline(&buffer, "LRP result.color.rgb, TMP_FOG.x, R0, state.fog.color;\n"); + shader_addline(&buffer, "MOV result.color.a, R0.a;\n"); + } else { + shader_addline(&buffer, "LRP result.color.rgb, TMP_FOG.x, TMP_COLOR, state.fog.color;\n"); + shader_addline(&buffer, "MOV result.color.a, TMP_COLOR.a;\n"); + } } shader_addline(&buffer, "END\n"); @@ -523,11 +573,49 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader IWineD3DPixelShaderImpl *This =(IWineD3DPixelShaderImpl *)iface; IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device; CONST DWORD *function = This->baseShader.function; + UINT i, sampler; + IWineD3DBaseTextureImpl *texture; TRACE("(%p) : function %p\n", iface, function); - /* We're already compiled. */ - if (This->baseShader.is_compiled) return WINED3D_OK; + /* We're already compiled, but check if any of the hardcoded stateblock assumptions + * changed. + */ + if (This->baseShader.is_compiled) { + char srgbenabled = deviceImpl->stateBlock->renderState[WINED3DRS_SRGBWRITEENABLE] ? 1 : 0; + for(i = 0; i < This->baseShader.num_sampled_samplers; i++) { + sampler = This->baseShader.sampled_samplers[i]; + texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler]; + if(texture && texture->baseTexture.shader_conversion_group != This->baseShader.sampled_format[sampler]) { + WARN("Recompiling shader %p due to format change on sampler %d\n", This, sampler); + WARN("Old format group %s, new is %s\n", + debug_d3dformat(This->baseShader.sampled_format[sampler]), + debug_d3dformat(texture->baseTexture.shader_conversion_group)); + goto recompile; + } + } + + /* TODO: Check projected textures */ + /* TODO: Check texture types(2D, Cube, 3D) */ + + if(srgbenabled != This->srgb_enabled && This->srgb_mode_hardcoded) { + WARN("Recompiling shader because srgb correction is different and hardcoded\n"); + goto recompile; + } + + return WINED3D_OK; + + recompile: + if(This->baseShader.recompile_count > 50) { + FIXME("Shader %p recompiled more than 50 times\n", This); + } else { + This->baseShader.recompile_count++; + } + + if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) { + destroy_glsl_pshader(This); + } + } /* We don't need to compile */ if (!function) { @@ -547,6 +635,9 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_CompileShader(IWineD3DPixelShader /* FIXME: validate reg_maps against OpenGL */ } + /* Reset fields tracking stateblock values beeing hardcoded in the shader */ + This->baseShader.num_sampled_samplers = 0; + /* Generate the HW shader */ TRACE("(%p) : Generating hardware program\n", This); IWineD3DPixelShaderImpl_GenerateShader(iface, &This->baseShader.reg_maps, function); diff --git a/dlls/wined3d/resource.c b/dlls/wined3d/resource.c index 6999f060c05..a75bcbd46ca 100644 --- a/dlls/wined3d/resource.c +++ b/dlls/wined3d/resource.c @@ -71,7 +71,7 @@ void IWineD3DResourceImpl_CleanUp(IWineD3DResource *iface){ TRACE("(%p) Cleaning up resource\n", This); if (This->resource.pool == WINED3DPOOL_DEFAULT) { TRACE("Decrementing device memory pool by %u\n", This->resource.size); - globalChangeGlRam(-This->resource.size); + WineD3DAdapterChangeGLRam(This->resource.wineD3DDevice, -This->resource.size); } LIST_FOR_EACH_SAFE(e1, e2, &This->resource.privateData) { diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index fbd95ed8548..929260b0a47 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -1559,12 +1559,6 @@ static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]); } - -static void state_srgbwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { - if(stateblock->renderState[WINED3DRS_SRGBWRITEENABLE]) - FIXME("Render state WINED3DRS_SRGBWRITEENABLE not yet implemented\n"); -} - static void state_separateblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { TRACE("Stub\n"); if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) @@ -3827,7 +3821,7 @@ const struct StateEntry StateTable[] = { /*191, WINED3DRS_COLORWRITEENABLE2 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, { /*192, WINED3DRS_COLORWRITEENABLE3 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, { /*193, WINED3DRS_BLENDFACTOR */ STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, - { /*194, WINED3DRS_SRGBWRITEENABLE */ STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), state_srgbwrite }, + { /*194, WINED3DRS_SRGBWRITEENABLE */ STATE_PIXELSHADER, pixelshader }, { /*195, WINED3DRS_DEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, { /*196, undefined */ 0, state_undefined }, { /*197, undefined */ 0, state_undefined }, diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 1ab0c727325..0b5d06698a7 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1504,8 +1504,8 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ } else { /* Not supported by GL_ATI_envmap_bumpmap */ *format = GL_BGRA; - *internal = GL_RGBA8; - *type = GL_UNSIGNED_BYTE; + *internal = GL_RGB8; + *type = GL_UNSIGNED_INT_8_8_8_8_REV; } break; @@ -1523,8 +1523,8 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break; *convert = CONVERT_V16U16; *format = GL_BGR; - *internal = GL_RGB16; - *type = GL_SHORT; + *internal = GL_RGB16_EXT; + *type = GL_UNSIGNED_SHORT; *target_bpp = 6; /* What should I do here about GL_ATI_envmap_bumpmap? * Convert it or allow data loss by loading it into a 8 bit / channel texture? @@ -1733,6 +1733,25 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN break; } + case CONVERT_V16U16: + { + unsigned int x, y; + DWORD *Source; + unsigned short *Dest; + for(y = 0; y < height; y++) { + Source = (DWORD *) (src + y * pitch); + Dest = (unsigned short *) (dst + y * outpitch); + for (x = 0; x < width; x++ ) { + DWORD color = (*Source++); + /* B */ Dest[0] = 0xffff; + /* G */ Dest[1] = (color >> 16) + 32768; /* V */ + /* R */ Dest[2] = (color ) + 32768; /* U */ + Dest += 3; + } + } + break; + } + case CONVERT_Q8W8V8U8: { unsigned int x, y; @@ -1788,7 +1807,21 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN } } } else { - FIXME("Add D3DFMT_L6V5U5 emulation using standard unsigned RGB and shaders\n"); + for(y = 0; y < height; y++) { + unsigned short *Dest_s = (unsigned short *) (dst + y * outpitch); + Source = (WORD *) (src + y * pitch); + for (x = 0; x < width; x++ ) { + short color = (*Source++); + unsigned char l = ((color >> 10) & 0xfc); + short v = ((color >> 5) & 0x3e); + short u = ((color ) & 0x1f); + short v_conv = v + 16; + short u_conv = u + 16; + + *Dest_s = ((v_conv << 11) & 0xf800) | ((l << 5) & 0x7e0) | (u_conv & 0x1f); + Dest_s += 1; + } + } } break; } @@ -1820,7 +1853,17 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN * shaders if the shader is adjusted. (There's no use for this format in gl's * standard fixed function pipeline anyway). */ - FIXME("Implement CONVERT_X8L8V8U8 with standard unsigned GL_RGB\n"); + for(y = 0; y < height; y++) { + Source = (DWORD *) (src + y * pitch); + Dest = (unsigned char *) (dst + y * outpitch); + for (x = 0; x < width; x++ ) { + long color = (*Source++); + /* B */ Dest[0] = ((color >> 16) & 0xff); /* L */ + /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */ + /* R */ Dest[2] = (color & 0xff) + 128; /* U */ + Dest += 4; + } + } } break; } diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index d5131e17b2a..bd1d7d385af 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -27,8 +27,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); -#define GLINFO_LOCATION This->adapter->gl_info - /***************************************************************************** * Pixel format array */ @@ -210,9 +208,11 @@ static inline int getFmtIdx(WINED3DFORMAT fmt) { return -1; } +#define GLINFO_LOCATION (*gl_info) BOOL initPixelFormats(WineD3D_GL_Info *gl_info) { unsigned int src; + int dst; gl_info->gl_formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(formats) / sizeof(formats[0]) * sizeof(gl_info->gl_formats[0])); @@ -222,15 +222,66 @@ BOOL initPixelFormats(WineD3D_GL_Info *gl_info) * after this loop */ for(src = 0; src < sizeof(gl_formats_template) / sizeof(gl_formats_template[0]); src++) { - int dst = getFmtIdx(gl_formats_template[src].fmt); + dst = getFmtIdx(gl_formats_template[src].fmt); gl_info->gl_formats[dst].glInternal = gl_formats_template[src].glInternal; gl_info->gl_formats[dst].glGammaInternal = gl_formats_template[src].glGammaInternal; gl_info->gl_formats[dst].glFormat = gl_formats_template[src].glFormat; gl_info->gl_formats[dst].glType = gl_formats_template[src].glType; + gl_info->gl_formats[dst].conversion_group= WINED3DFMT_UNKNOWN; + } + + /* V8U8 is supported natively by GL_ATI_envmap_bumpmap and GL_NV_texture_shader. + * V16U16 is only supported by GL_NV_texture_shader. The formats need fixup if + * their extensions are not available. + * + * In theory, V8U8 and V16U16 need a fixup of the undefined blue channel. OpenGL + * returns 0.0 when sampling from it, DirectX 1.0. This is disabled until we find + * an application that needs this because it causes performance problems due to + * shader recompiling in some games. + */ + if(!GL_SUPPORT(ATI_ENVMAP_BUMPMAP) && !GL_SUPPORT(NV_TEXTURE_SHADER2)) { + /* signed -> unsigned fixup */ + dst = getFmtIdx(WINED3DFMT_V8U8); + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V8U8; + dst = getFmtIdx(WINED3DFMT_V16U16); + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V8U8; + } else if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) { + /* signed -> unsigned fixup */ + dst = getFmtIdx(WINED3DFMT_V16U16); + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V16U16; + } else { + /* Blue = 1.0 fixup, disabled for now */ +#if 0 + dst = getFmtIdx(WINED3DFMT_V8U8); + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V8U8; + dst = getFmtIdx(WINED3DFMT_V16U16); + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_V8U8; +#endif + } + + if(!GL_SUPPORT(NV_TEXTURE_SHADER)) { + /* If GL_NV_texture_shader is not supported, those formats are converted, incompatibly + * with each other + */ + dst = getFmtIdx(WINED3DFMT_L6V5U5); + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_L6V5U5; + dst = getFmtIdx(WINED3DFMT_X8L8V8U8); + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_X8L8V8U8; + dst = getFmtIdx(WINED3DFMT_Q8W8V8U8); + gl_info->gl_formats[dst].conversion_group = WINED3DFMT_Q8W8V8U8; + } else { + /* If GL_NV_texture_shader is supported, WINED3DFMT_L6V5U5 and WINED3DFMT_X8L8V8U8 + * are converted at surface loading time, but they do not need any modification in + * the shader, thus they are compatible with all WINED3DFMT_UNKNOWN group formats. + * WINED3DFMT_Q8W8V8U8 doesn't even need load-time conversion + */ } return TRUE; } +#undef GLINFO_LOCATION + +#define GLINFO_LOCATION This->adapter->gl_info const StaticPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt, WineD3D_GL_Info *gl_info, const GlPixelFormatDesc **glDesc) { diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c index 2443e336689..ebe09bd2605 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -46,19 +46,6 @@ wined3d_settings_t wined3d_settings = NULL /* No wine logo by default */ }; -WineD3DGlobalStatistics *wineD3DGlobalStatistics = NULL; - -long globalChangeGlRam(long glram){ - /* FIXME: replace this function with object tracking */ - int result; - - wineD3DGlobalStatistics->glsurfaceram += glram; - TRACE("Adjusted gl ram by %ld to %d\n", glram, wineD3DGlobalStatistics->glsurfaceram); - result = wineD3DGlobalStatistics->glsurfaceram; - return result; - -} - IWineD3D* WINAPI WineDirect3DCreate(UINT SDKVersion, UINT dxVersion, IUnknown *parent) { IWineD3DImpl* object; @@ -76,13 +63,6 @@ IWineD3D* WINAPI WineDirect3DCreate(UINT SDKVersion, UINT dxVersion, IUnknown *p object->ref = 1; object->parent = parent; - /*Create a structure for storing global data in*/ - if(wineD3DGlobalStatistics == NULL){ - TRACE("Creating global statistics store\n"); - wineD3DGlobalStatistics = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wineD3DGlobalStatistics)); - - } - TRACE("Created WineD3D object @ %p for d3d%d support\n", object, dxVersion); return (IWineD3D *)object; @@ -113,8 +93,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) DWORD len; WNDCLASSA wc; - wined3d_settings.emulated_textureram = 64*1024*1024; - /* We need our own window class for a fake window which we use to retrieve GL capabilities */ /* We might need CS_OWNDC in the future if we notice strange things on Windows. * Various articles/posts about OpenGL problems on Windows recommend this. */ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index b7e08fc4b35..8844ffa0b42 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -203,12 +203,14 @@ typedef struct wined3d_settings_s { extern wined3d_settings_t wined3d_settings; /* Shader backends */ +struct SHADER_OPCODE_ARG; typedef struct { void (*shader_select)(IWineD3DDevice *iface, BOOL usePS, BOOL useVS); void (*shader_select_depth_blt)(IWineD3DDevice *iface); void (*shader_load_constants)(IWineD3DDevice *iface, char usePS, char useVS); void (*shader_cleanup)(IWineD3DDevice *iface); + void (*shader_color_correction)(struct SHADER_OPCODE_ARG *arg); } shader_backend_t; extern const shader_backend_t glsl_shader_backend; @@ -324,23 +326,6 @@ typedef struct IWineD3DSurfaceImpl IWineD3DSurfaceImpl; typedef struct IWineD3DPaletteImpl IWineD3DPaletteImpl; typedef struct IWineD3DDeviceImpl IWineD3DDeviceImpl; -/* Tracking */ - -/* TODO: Move some of this to the device */ -long globalChangeGlRam(long glram); - -/* Memory and object tracking */ - -/*Structure for holding information on all direct3d objects -useful for making sure tracking is ok and when release is called on a device! -and probably quite handy for debugging and dumping states out -*/ -typedef struct WineD3DGlobalStatistics { - int glsurfaceram; /* The aproximate amount of glTexture memory allocated for textures */ -} WineD3DGlobalStatistics; - -extern WineD3DGlobalStatistics* wineD3DGlobalStatistics; - /* Global variables */ extern const float identity[16]; @@ -595,10 +580,13 @@ struct WineD3DAdapter WCHAR DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */ int nCfgs; WineD3D_PixelFormat *cfgs; + unsigned int TextureRam; /* Amount of texture memory both video ram + AGP/TurboCache/HyperMemory/.. */ + unsigned int UsedTextureRam; }; extern BOOL InitAdapters(void); extern BOOL initPixelFormats(WineD3D_GL_Info *gl_info); +extern long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram); /***************************************************************************** * High order patch management @@ -932,6 +920,7 @@ typedef struct IWineD3DBaseTextureClass DWORD sampler; BOOL is_srgb; UINT srgb_mode_change_count; + WINED3DFORMAT shader_conversion_group; } IWineD3DBaseTextureClass; typedef struct IWineD3DBaseTextureImpl @@ -1604,7 +1593,6 @@ unsigned int count_bits(unsigned int mask); /*** class static members ***/ void IWineD3DBaseTextureImpl_CleanUp(IWineD3DBaseTexture *iface); -struct SHADER_OPCODE_ARG; typedef void (*SHADER_HANDLER) (struct SHADER_OPCODE_ARG*); /* Struct to maintain a list of GLSL shader programs and their associated pixel and @@ -1794,6 +1782,10 @@ extern void pshader_hw_texm3x3spec(SHADER_OPCODE_ARG* arg); extern void pshader_hw_texm3x3vspec(SHADER_OPCODE_ARG* arg); extern void pshader_hw_texdepth(SHADER_OPCODE_ARG* arg); extern void pshader_hw_texkill(SHADER_OPCODE_ARG* arg); +extern void pshader_hw_texdp3tex(SHADER_OPCODE_ARG* arg); +extern void pshader_hw_texdp3(SHADER_OPCODE_ARG* arg); +extern void pshader_hw_texm3x3(SHADER_OPCODE_ARG* arg); +extern void pshader_hw_texm3x2depth(SHADER_OPCODE_ARG* arg); /* ARB vertex shader prototypes */ extern void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg); @@ -1898,6 +1890,17 @@ typedef struct IWineD3DBaseShaderClass struct list constantsI; shader_reg_maps reg_maps; + /* Pixel formats of sampled textures, for format conversion. This + * represents the formats found during compilation, it is not initialized + * on the first parser pass. It is needed to check if the shader + * needs recompilation to adjust the format conversion + */ + WINED3DFORMAT sampled_format[MAX_COMBINED_SAMPLERS]; + UINT sampled_samplers[MAX_COMBINED_SAMPLERS]; + UINT num_sampled_samplers; + + UINT recompile_count; + /* Pointer to the parent device */ IWineD3DDevice *device; @@ -2068,6 +2071,10 @@ typedef struct IWineD3DPixelShaderImpl { /* Some information about the shader behavior */ char needsbumpmat; UINT bumpenvmatconst; + char srgb_enabled; + char srgb_mode_hardcoded; + UINT srgb_low_const; + UINT srgb_cmp_const; #if 0 /* needs reworking */ PSHADERINPUTDATA input; @@ -2078,6 +2085,13 @@ typedef struct IWineD3DPixelShaderImpl { extern const SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[]; extern const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl; +/* sRGB correction constants */ +static const float srgb_cmp = 0.0031308; +static const float srgb_mul_low = 12.92; +static const float srgb_pow = 0.41666; +static const float srgb_mul_high = 1.055; +static const float srgb_sub_high = 0.055; + /***************************************************************************** * IWineD3DPalette implementation structure */ diff --git a/dlls/wineps.drv/init.c b/dlls/wineps.drv/init.c index 82ed4394fa8..0d1ddd1511c 100644 --- a/dlls/wineps.drv/init.c +++ b/dlls/wineps.drv/init.c @@ -177,7 +177,7 @@ static void PSDRV_UpdateDevCaps( PSDRV_PDEVICE *physDev ) break; } - if(!page) { + if(&page->entry == &physDev->pi->ppd->PageSizes) { FIXME("Can't find page\n"); physDev->ImageableArea.left = 0; physDev->ImageableArea.right = 0; diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 091aee5eabd..b867abd5693 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -72,7 +72,7 @@ typedef struct wine_glextension { struct { const char *funcName; void *funcAddress; - } extEntryPoints[8]; + } extEntryPoints[9]; } WineGLExtension; struct WineGLInfo { @@ -277,6 +277,8 @@ MAKE_FUNCPTR(glReadPixels) MAKE_FUNCPTR(glScissor) MAKE_FUNCPTR(glTexImage2D) MAKE_FUNCPTR(glViewport) +MAKE_FUNCPTR(glFinish) +MAKE_FUNCPTR(glFlush) #undef MAKE_FUNCPTR static BOOL X11DRV_WineGL_InitOpenglInfo(void) @@ -428,6 +430,8 @@ LOAD_FUNCPTR(glReadPixels) LOAD_FUNCPTR(glScissor) LOAD_FUNCPTR(glTexImage2D) LOAD_FUNCPTR(glViewport) +LOAD_FUNCPTR(glFinish) +LOAD_FUNCPTR(glFlush) #undef LOAD_FUNCPTR /* It doesn't matter if these fail. They'll only be used if the driver reports @@ -2054,6 +2058,20 @@ static void WINAPI X11DRV_wglViewport(GLint x, GLint y, GLsizei width, GLsizei h } } +static void WINAPI X11DRV_wglFinish(void) +{ + wine_tsx11_lock(); + pglFinish(); + wine_tsx11_unlock(); +} + +static void WINAPI X11DRV_wglFlush(void) +{ + wine_tsx11_lock(); + pglFlush(); + wine_tsx11_unlock(); +} + /** * X11DRV_wglGetExtensionsStringARB * @@ -3093,6 +3111,8 @@ static const WineGLExtension WGL_internal_functions = { "wglIsEnabled", X11DRV_wglIsEnabled }, { "wglScissor", X11DRV_wglScissor }, { "wglViewport", X11DRV_wglViewport }, + { "wglFinish", X11DRV_wglFinish }, + { "wglFlush", X11DRV_wglFlush }, } }; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index b0b6d8a9183..0f91b6e6a3e 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -20,6 +20,7 @@ */ #include "config.h" +#include "wine/port.h" #include #include @@ -48,8 +49,10 @@ #include "x11drv.h" #include "xvidmode.h" #include "xrandr.h" +#include "xcomposite.h" #include "wine/server.h" #include "wine/debug.h" +#include "wine/library.h" WINE_DEFAULT_DEBUG_CHANNEL(x11drv); WINE_DECLARE_DEBUG_CHANNEL(synchronous); @@ -73,6 +76,7 @@ Window root_window; int dxgrab = 0; int usexvidmode = 1; int usexrandr = 1; +int usexcomposite = 1; int use_xkb = 1; int use_take_focus = 1; int use_primary_selection = 0; @@ -370,6 +374,70 @@ static void setup_options(void) if (hkey) RegCloseKey( hkey ); } +#ifdef SONAME_LIBXCOMPOSITE + +#define MAKE_FUNCPTR(f) typeof(f) * p##f; +MAKE_FUNCPTR(XCompositeQueryExtension) +MAKE_FUNCPTR(XCompositeQueryVersion) +MAKE_FUNCPTR(XCompositeVersion) +MAKE_FUNCPTR(XCompositeRedirectWindow) +MAKE_FUNCPTR(XCompositeRedirectSubwindows) +MAKE_FUNCPTR(XCompositeUnredirectWindow) +MAKE_FUNCPTR(XCompositeUnredirectSubwindows) +MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip) +MAKE_FUNCPTR(XCompositeNameWindowPixmap) +MAKE_FUNCPTR(XCompositeGetOverlayWindow) +MAKE_FUNCPTR(XCompositeReleaseOverlayWindow) +#undef MAKE_FUNCPTR + +static int xcomp_event_base; +static int xcomp_error_base; + +static void X11DRV_XComposite_Init(void) +{ + void *xcomposite_handle = wine_dlopen(SONAME_LIBXCOMPOSITE, RTLD_NOW, NULL, 0); + if (!xcomposite_handle) + { + TRACE("Unable to open %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE); + usexcomposite = 0; + return; + } + +#define LOAD_FUNCPTR(f) \ + if((p##f = wine_dlsym(xcomposite_handle, #f, NULL, 0)) == NULL) \ + goto sym_not_found; + LOAD_FUNCPTR(XCompositeQueryExtension) + LOAD_FUNCPTR(XCompositeQueryVersion) + LOAD_FUNCPTR(XCompositeVersion) + LOAD_FUNCPTR(XCompositeRedirectWindow) + LOAD_FUNCPTR(XCompositeRedirectSubwindows) + LOAD_FUNCPTR(XCompositeUnredirectWindow) + LOAD_FUNCPTR(XCompositeUnredirectSubwindows) + LOAD_FUNCPTR(XCompositeCreateRegionFromBorderClip) + LOAD_FUNCPTR(XCompositeNameWindowPixmap) + LOAD_FUNCPTR(XCompositeGetOverlayWindow) + LOAD_FUNCPTR(XCompositeReleaseOverlayWindow) +#undef LOAD_FUNCPTR + + if(!pXCompositeQueryExtension(gdi_display, &xcomp_event_base, + &xcomp_error_base)) { + TRACE("XComposite extension could not be queried; disabled\n"); + wine_dlclose(xcomposite_handle, NULL, 0); + xcomposite_handle = NULL; + usexcomposite = 0; + return; + } + TRACE("XComposite is up and running error_base = %d\n", xcomp_error_base); + return; + +sym_not_found: + TRACE("Unable to load function pointers from %s, XComposite disabled\n", SONAME_LIBXCOMPOSITE); + wine_dlclose(xcomposite_handle, NULL, 0); + xcomposite_handle = NULL; + usexcomposite = 0; +} +#endif /* defined(SONAME_LIBXCOMPOSITE) */ + /*********************************************************************** * X11DRV process initialisation routine @@ -442,6 +510,9 @@ static BOOL process_attach(void) /* initialize XRandR */ X11DRV_XRandR_Init(); #endif +#ifdef SONAME_LIBXCOMPOSITE + X11DRV_XComposite_Init(); +#endif X11DRV_ClipCursor( NULL ); X11DRV_InitKeyboard(); diff --git a/dlls/winex11.drv/xcomposite.h b/dlls/winex11.drv/xcomposite.h new file mode 100644 index 00000000000..307c0ef72a6 --- /dev/null +++ b/dlls/winex11.drv/xcomposite.h @@ -0,0 +1,45 @@ +/* + * Wine X11DRV XComposite interface + * + * Copyright 2007 Chris Robinson + * + * 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 + */ +#ifndef __WINE_XCOMPOSITE_H +#define __WINE_XCOMPOSITE_H + +#ifndef __WINE_CONFIG_H +# error You must include config.h to use this header +#endif + +#ifdef SONAME_LIBXCOMPOSITE + +#include +#define MAKE_FUNCPTR(f) extern typeof(f) * p##f; +MAKE_FUNCPTR(XCompositeQueryExtension) +MAKE_FUNCPTR(XCompositeQueryVersion) +MAKE_FUNCPTR(XCompositeVersion) +MAKE_FUNCPTR(XCompositeRedirectWindow) +MAKE_FUNCPTR(XCompositeRedirectSubwindows) +MAKE_FUNCPTR(XCompositeUnredirectWindow) +MAKE_FUNCPTR(XCompositeUnredirectSubwindows) +MAKE_FUNCPTR(XCompositeCreateRegionFromBorderClip) +MAKE_FUNCPTR(XCompositeNameWindowPixmap) +MAKE_FUNCPTR(XCompositeGetOverlayWindow) +MAKE_FUNCPTR(XCompositeReleaseOverlayWindow) +#undef MAKE_FUNCPTR + +#endif /* defined(SONAME_LIBXCOMPOSITE) */ +#endif /* __WINE_XCOMPOSITE_H */ diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index 5e95a122cb3..0edca74598c 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -208,13 +208,14 @@ BOOL WININET_FreeHandle( HINTERNET hinternet ) TRACE( "destroying handle %d for object %p\n", handle+1, info); WININET_Handles[handle] = NULL; ret = TRUE; - if( WININET_dwNextHandle > handle ) - WININET_dwNextHandle = handle; } } LeaveCriticalSection( &WININET_cs ); + /* As on native when the equivalent of WININET_Release is called, the handle + * is already invalid, but if a new handle is created at this time it does + * not yet get assigned the freed handle number */ if( info ) { /* Free all children as native does */ @@ -227,6 +228,13 @@ BOOL WININET_FreeHandle( HINTERNET hinternet ) WININET_Release( info ); } + EnterCriticalSection( &WININET_cs ); + + if( WININET_dwNextHandle > handle && !WININET_Handles[handle] ) + WININET_dwNextHandle = handle; + + LeaveCriticalSection( &WININET_cs ); + return ret; } @@ -1006,8 +1014,8 @@ BOOL WINAPI InternetCloseHandle(HINTERNET hInternet) return FALSE; } - WININET_FreeHandle( hInternet ); WININET_Release( lpwh ); + WININET_FreeHandle( hInternet ); return TRUE; } diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 13878a7aec3..c517f7eeabd 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1405,6 +1405,20 @@ int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen) } else { +#ifdef IPV6_V6ONLY + const struct sockaddr_in6 *in6 = (const struct sockaddr_in6*) &uaddr; + if (name->sa_family == WS_AF_INET6 && + !memcmp(&in6->sin6_addr, &in6addr_any, sizeof(struct in6_addr))) + { + int enable = 1; + if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(enable)) == -1) + { + release_sock_fd( s, fd ); + SetLastError(WSAEAFNOSUPPORT); + return INVALID_SOCKET; + } + } +#endif if (bind(fd, &uaddr.addr, uaddrlen) < 0) { int loc_errno = errno; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index d04552e7211..8225f5f9d60 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -1909,6 +1909,52 @@ end: CloseHandle(hEvent); } +static void test_ipv6only(void) +{ + SOCKET v4 = INVALID_SOCKET, + v6 = INVALID_SOCKET; + struct sockaddr_in sin4; + struct sockaddr_in6 sin6; + int ret; + + memset(&sin4, 0, sizeof(sin4)); + sin4.sin_family = AF_INET; + sin4.sin_port = htons(SERVERPORT); + + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_port = htons(SERVERPORT); + + v6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + if (v6 == INVALID_SOCKET) { + skip("Could not create IPv6 socket (LastError: %d; %d expected if IPv6 not available).\n", + WSAGetLastError(), WSAEAFNOSUPPORT); + goto end; + } + ret = bind(v6, (struct sockaddr*)&sin6, sizeof(sin6)); + if (ret) { + skip("Could not bind IPv6 address (LastError: %d).\n", + WSAGetLastError()); + goto end; + } + + v4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (v4 == INVALID_SOCKET) { + skip("Could not create IPv4 socket (LastError: %d).\n", + WSAGetLastError()); + goto end; + } + ret = bind(v4, (struct sockaddr*)&sin4, sizeof(sin4)); + ok(!ret, "Could not bind IPv4 address (LastError: %d; %d expected if IPv6 binds to IPv4 as well).\n", + WSAGetLastError(), WSAEADDRINUSE); + +end: + if (v4 != INVALID_SOCKET) + closesocket(v4); + if (v6 != INVALID_SOCKET) + closesocket(v6); +} + /**************** Main program ***************/ START_TEST( sock ) @@ -1946,5 +1992,7 @@ START_TEST( sock ) test_send(); test_write_events(); + test_ipv6only(); + Exit(); } diff --git a/dlls/wtsapi32/wtsapi32.c b/dlls/wtsapi32/wtsapi32.c index cec23eec9f5..9935d363d24 100644 --- a/dlls/wtsapi32/wtsapi32.c +++ b/dlls/wtsapi32/wtsapi32.c @@ -204,3 +204,21 @@ BOOL WINAPI WTSWaitSystemEvent(HANDLE hServer, DWORD Mask, DWORD* Flags) FIXME("Stub %p 0x%08x %p\n", hServer, Mask, Flags); return FALSE; } + +/************************************************************ + * WTSRegisterSessionNotification (WTSAPI32.@) + */ +BOOL WINAPI WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags) +{ + FIXME("Stub %p 0x%08x\n", hWnd, dwFlags); + return FALSE; +} + +/************************************************************ + * WTSUnRegisterSessionNotification (WTSAPI32.@) + */ +BOOL WINAPI WTSUnRegisterSessionNotification(HWND hWnd) +{ + FIXME("Stub %p\n", hWnd); + return FALSE; +} diff --git a/dlls/wtsapi32/wtsapi32.spec b/dlls/wtsapi32/wtsapi32.spec index 0cfa7e319e3..059b6daa540 100644 --- a/dlls/wtsapi32/wtsapi32.spec +++ b/dlls/wtsapi32/wtsapi32.spec @@ -14,6 +14,7 @@ @ stdcall WTSQuerySessionInformationW(long long long ptr ptr) @ stub WTSQueryUserConfigA @ stub WTSQueryUserConfigW +@ stdcall WTSRegisterSessionNotification(long long) @ stub WTSSendMessageA @ stub WTSSendMessageW @ stub WTSSetSessionInformationA @@ -22,6 +23,7 @@ @ stub WTSSetUserConfigW @ stub WTSShutdownSystem @ stub WTSTerminateProcess +@ stdcall WTSUnRegisterSessionNotification(long) @ stub WTSVirtualChannelClose @ stub WTSVirtualChannelOpen @ stub WTSVirtualChannelPurgeInput diff --git a/include/config.h.in b/include/config.h.in index e21e513ba97..8df3a1a93b1 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -888,6 +888,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_X11_EXTENSIONS_SHAPE_H +/* Define to 1 if you have the header file. */ +#undef HAVE_X11_EXTENSIONS_XCOMPOSITE_H + /* Define to 1 if you have the header file. */ #undef HAVE_X11_EXTENSIONS_XF86VMODE_H @@ -1014,6 +1017,9 @@ /* Define to the soname of the libX11 library. */ #undef SONAME_LIBX11 +/* Define to the soname of the libXcomposite library. */ +#undef SONAME_LIBXCOMPOSITE + /* Define to the soname of the libXcursor library. */ #undef SONAME_LIBXCURSOR diff --git a/include/iads.idl b/include/iads.idl index 08cbfe89ed0..ce38bfefc1d 100644 --- a/include/iads.idl +++ b/include/iads.idl @@ -18,6 +18,30 @@ import "oaidl.idl"; +typedef enum +{ + ADS_RIGHT_DS_CREATE_CHILD = 0x00000001, + ADS_RIGHT_DS_DELETE_CHILD = 0x00000002, + ADS_RIGHT_ACTRL_DS_LIST = 0x00000004, + ADS_RIGHT_DS_SELF = 0x00000008, + ADS_RIGHT_DS_READ_PROP = 0x00000010, + ADS_RIGHT_DS_WRITE_PROP = 0x00000020, + ADS_RIGHT_DS_DELETE_TREE = 0x00000040, + ADS_RIGHT_DS_LIST_OBJECT = 0x00000080, + ADS_RIGHT_DS_CONTROL_ACCESS = 0x00000100, + + ADS_RIGHT_DELETE = 0x00010000, + ADS_RIGHT_READ_CONTROL = 0x00020000, + ADS_RIGHT_WRITE_DAC = 0x00040000, + ADS_RIGHT_WRITE_OWNER = 0x00080000, + ADS_RIGHT_SYNCHRONIZE = 0x00100000, + ADS_RIGHT_ACCESS_SYSTEM_SECURITY = 0x00200000, + + ADS_RIGHT_GENERIC_ALL = 0x10000000, + ADS_RIGHT_GENERIC_EXECUTE = 0x20000000, + ADS_RIGHT_GENERIC_WRITE = 0x40000000, + ADS_RIGHT_GENERIC_READ = 0x80000000 +} ADS_RIGHTS_ENUM; /***************************************************************************** * IADsContainer interface diff --git a/include/setupapi.h b/include/setupapi.h index e4a0fc37dac..d52790d63a4 100644 --- a/include/setupapi.h +++ b/include/setupapi.h @@ -1456,8 +1456,8 @@ BOOL WINAPI SetupDiCreateDeviceInfoW(HDEVINFO, PCWSTR, CONST GUID*, PCWSTR, BOOL WINAPI SetupDiCreateDeviceInterfaceA(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, PCSTR, DWORD, PSP_DEVICE_INTERFACE_DATA); BOOL WINAPI SetupDiCreateDeviceInterfaceW(HDEVINFO, PSP_DEVINFO_DATA, const GUID *, PCWSTR, DWORD, PSP_DEVICE_INTERFACE_DATA); #define SetupDiCreateDeviceInterface WINELIB_NAME_AW(SetupDiCreateDeviceInterface) -HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(HDEVINFO, PSP_DEVINFO_DATA, DWORD, REGSAM, HINF, PCSTR); -HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(HDEVINFO, PSP_DEVINFO_DATA, DWORD, REGSAM, HINF, PCWSTR); +HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, REGSAM, HINF, PCSTR); +HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, REGSAM, HINF, PCWSTR); #define SetupDiCreateDeviceInterfaceRegKey WINELIB_NAME_AW(SetupDiCreateDeviceInterfaceRegKey) BOOL WINAPI SetupDiCreateDevRegKeyA(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, HINF, PCSTR); BOOL WINAPI SetupDiCreateDevRegKeyW(HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, HINF, PCWSTR); diff --git a/include/shlobj.h b/include/shlobj.h index 77e09ccd5ba..d93a69d112c 100644 --- a/include/shlobj.h +++ b/include/shlobj.h @@ -43,6 +43,7 @@ UINT WINAPI SHAddFromPropSheetExtArray(HPSXA,LPFNADDPROPSHEETPAGE,LPARAM LPVOID WINAPI SHAlloc(ULONG); HRESULT WINAPI SHCoCreateInstance(LPCWSTR,const CLSID*,IUnknown*,REFIID,LPVOID*); HPSXA WINAPI SHCreatePropSheetExtArray(HKEY,LPCWSTR,UINT); +HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY,LPCWSTR,UINT,IDataObject*); DWORD WINAPI SHCLSIDFromStringA(LPCSTR,CLSID*); DWORD WINAPI SHCLSIDFromStringW(LPCWSTR,CLSID*); #define SHCLSIDFromString WINELIB_NAME_AW(SHCLSIDFromString) @@ -149,7 +150,6 @@ typedef struct */ typedef GUID SHELLVIEWID; -#define SV_CLASS_NAME ("SHELLDLL_DefView") #define FCIDM_SHVIEWFIRST 0x0000 /* undocumented */ diff --git a/include/winbase.h b/include/winbase.h index af6a38c7c71..2ad4314a5e6 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -1243,6 +1243,7 @@ ATOM WINAPI AddAtomA(LPCSTR); ATOM WINAPI AddAtomW(LPCWSTR); #define AddAtom WINELIB_NAME_AW(AddAtom) BOOL WINAPI AddAuditAccessAce(PACL,DWORD,DWORD,PSID,BOOL,BOOL); +BOOL WINAPI AddAuditAccessAceEx(PACL,DWORD,DWORD,DWORD,PSID,BOOL,BOOL); VOID WINAPI AddRefActCtx(HANDLE); PVOID WINAPI AddVectoredExceptionHandler(ULONG,PVECTORED_EXCEPTION_HANDLER); BOOL WINAPI AdjustTokenGroups(HANDLE,BOOL,PTOKEN_GROUPS,DWORD,PTOKEN_GROUPS,PDWORD); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index a43722af084..8f1213eacd6 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4162,6 +4162,84 @@ struct get_token_statistics_reply }; + +struct create_completion_request +{ + struct request_header __header; + unsigned int access; + unsigned int attributes; + unsigned int concurrent; + obj_handle_t rootdir; + /* VARARG(filename,string); */ +}; +struct create_completion_reply +{ + struct reply_header __header; + obj_handle_t handle; +}; + + + +struct open_completion_request +{ + struct request_header __header; + unsigned int access; + unsigned int attributes; + obj_handle_t rootdir; + /* VARARG(filename,string); */ +}; +struct open_completion_reply +{ + struct reply_header __header; + obj_handle_t handle; +}; + + + +struct add_completion_request +{ + struct request_header __header; + obj_handle_t handle; + unsigned long ckey; + unsigned long cvalue; + unsigned long information; + unsigned int status; +}; +struct add_completion_reply +{ + struct reply_header __header; +}; + + + +struct remove_completion_request +{ + struct request_header __header; + obj_handle_t handle; +}; +struct remove_completion_reply +{ + struct reply_header __header; + unsigned long ckey; + unsigned long cvalue; + unsigned long information; + unsigned int status; +}; + + + +struct query_completion_request +{ + struct request_header __header; + obj_handle_t handle; +}; +struct query_completion_reply +{ + struct reply_header __header; + unsigned int depth; +}; + + enum request { REQ_new_process, @@ -4389,6 +4467,11 @@ enum request REQ_get_next_device_request, REQ_make_process_system, REQ_get_token_statistics, + REQ_create_completion, + REQ_open_completion, + REQ_add_completion, + REQ_remove_completion, + REQ_query_completion, REQ_NB_REQUESTS }; @@ -4621,6 +4704,11 @@ union generic_request struct get_next_device_request_request get_next_device_request_request; struct make_process_system_request make_process_system_request; struct get_token_statistics_request get_token_statistics_request; + struct create_completion_request create_completion_request; + struct open_completion_request open_completion_request; + struct add_completion_request add_completion_request; + struct remove_completion_request remove_completion_request; + struct query_completion_request query_completion_request; }; union generic_reply { @@ -4851,8 +4939,13 @@ union generic_reply struct get_next_device_request_reply get_next_device_request_reply; struct make_process_system_reply make_process_system_reply; struct get_token_statistics_reply get_token_statistics_reply; + struct create_completion_reply create_completion_reply; + struct open_completion_reply open_completion_reply; + struct add_completion_reply add_completion_reply; + struct remove_completion_reply remove_completion_reply; + struct query_completion_reply query_completion_reply; }; -#define SERVER_PROTOCOL_VERSION 313 +#define SERVER_PROTOCOL_VERSION 314 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h index 1a04dd72b8e..3da14ef81b6 100644 --- a/include/wine/wined3d_gl.h +++ b/include/wine/wined3d_gl.h @@ -3691,6 +3691,7 @@ typedef BOOL (WINAPI * WINED3D_PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, typedef struct { GLint glInternal, glGammaInternal, glFormat, glType; + WINED3DFORMAT conversion_group; } GlPixelFormatDesc; #define USE_GL_FUNC(type, pfn) type pfn; @@ -3701,6 +3702,7 @@ typedef struct _WineD3D_GL_Info { GL_Vendors gl_vendor; GL_Cards gl_card; + UINT vidmem; DWORD gl_driver_version; CHAR gl_renderer[255]; /** diff --git a/include/winnt.h b/include/winnt.h index 63b19365d61..aecc2afefa7 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -3917,7 +3917,7 @@ typedef struct _ACE_HEADER { #define NO_PROPAGATE_INHERIT_ACE 0x04 #define INHERIT_ONLY_ACE 0x08 #define INHERITED_ACE 0x10 -#define VALID_INHERIT_FLAGS 0x0F +#define VALID_INHERIT_FLAGS 0x1F /* AceFlags mask for what events we (should) audit */ #define SUCCESSFUL_ACCESS_ACE_FLAG 0x40 diff --git a/include/winternl.h b/include/winternl.h index 541eb5835b9..88c36b1cf44 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1987,6 +1987,7 @@ NTSTATUS WINAPI RtlAddAccessDeniedAce(PACL,DWORD,DWORD,PSID); NTSTATUS WINAPI RtlAddAccessDeniedAceEx(PACL,DWORD,DWORD,DWORD,PSID); NTSTATUS WINAPI RtlAddAtomToAtomTable(RTL_ATOM_TABLE,const WCHAR*,RTL_ATOM*); NTSTATUS WINAPI RtlAddAuditAccessAce(PACL,DWORD,DWORD,PSID,BOOL,BOOL); +NTSTATUS WINAPI RtlAddAuditAccessAceEx(PACL,DWORD,DWORD,DWORD,PSID,BOOL,BOOL); void WINAPI RtlAddRefActivationContext(HANDLE); PVOID WINAPI RtlAddVectoredExceptionHandler(ULONG,PVECTORED_EXCEPTION_HANDLER); NTSTATUS WINAPI RtlAdjustPrivilege(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN); diff --git a/include/winuser.h b/include/winuser.h index b667aa5fca9..ef179940ada 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -443,6 +443,59 @@ typedef struct tagINPUT } DUMMYUNIONNAME; } INPUT, *PINPUT, *LPINPUT; +typedef HANDLE HRAWINPUT; + +typedef struct tagRAWINPUTDEVICELIST +{ + HANDLE hDevice; + DWORD dwType; +} RAWINPUTDEVICELIST, *PRAWINPUTDEVICELIST; + +typedef struct tagRAWHID { + DWORD dwSizeHid; + DWORD dwCount; + BYTE bRawData; +} RAWHID, *LPRAWHID; + +typedef struct tagRAWKEYBOARD { + USHORT MakeCode; + USHORT Flags; + USHORT Reserved; + USHORT VKey; + UINT Message; + ULONG ExtraInformation; +} RAWKEYBOARD, *PRAWKEYBOARD, *LPRAWKEYBOARD; + +typedef struct tagRAWMOUSE { + USHORT usFlags; + union { + ULONG ulButtons; + struct { + USHORT usButtonFlags; + USHORT usButtonData; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + ULONG ulRawButtons; + LONG lLastX; + LONG lLastY; + ULONG ulExtraInformation; +} RAWMOUSE, *PRAWMOUSE, *LPRAWMOUSE; + +typedef struct tagRAWINPUTHEADER { + DWORD dwType; + DWORD dwSize; + HANDLE hDevice; + WPARAM wParam; +} RAWINPUTHEADER, *PRAWINPUTHEADER; + +typedef struct tagRAWINPUT { + RAWINPUTHEADER header; + union { + RAWMOUSE mouse; + RAWKEYBOARD keyboard; + RAWHID hid; + } data; +} RAWINPUT, *PRAWINPUT, *LPRAWINPUT; typedef struct tagRAWINPUTDEVICE { USHORT usUsagePage; @@ -4457,6 +4510,7 @@ LRESULT WINAPI DefFrameProcW(HWND,HWND,UINT,WPARAM,LPARAM); LRESULT WINAPI DefMDIChildProcA(HWND,UINT,WPARAM,LPARAM); LRESULT WINAPI DefMDIChildProcW(HWND,UINT,WPARAM,LPARAM); #define DefMDIChildProc WINELIB_NAME_AW(DefMDIChildProc) +LRESULT WINAPI DefRawInputProc(PRAWINPUT*,INT,UINT); LRESULT WINAPI DefWindowProcA(HWND,UINT,WPARAM,LPARAM); LRESULT WINAPI DefWindowProcW(HWND,UINT,WPARAM,LPARAM); #define DefWindowProc WINELIB_NAME_AW(DefWindowProc) @@ -4613,8 +4667,14 @@ BOOL WINAPI GetKeyboardLayoutNameA(LPSTR); BOOL WINAPI GetKeyboardLayoutNameW(LPWSTR); #define GetKeyboardLayoutName WINELIB_NAME_AW(GetKeyboardLayoutName) SHORT WINAPI GetKeyState(INT); -HWND WINAPI GetLastActivePopup(HWND); -BOOL WINAPI GetLastInputInfo(PLASTINPUTINFO); +HWND WINAPI GetLastActivePopup(HWND); +BOOL WINAPI GetLastInputInfo(PLASTINPUTINFO); +UINT WINAPI GetRawInputBuffer(PRAWINPUT,PUINT,UINT); +INT WINAPI GetRawInputData(HRAWINPUT,UINT,LPVOID,PUINT,UINT); +UINT WINAPI GetRawInputDeviceInfoA(HANDLE,UINT,LPVOID,PUINT); +UINT WINAPI GetRawInputDeviceInfoW(HANDLE,UINT,LPVOID,PUINT); +#define GetRawInputDeviceInfo WINELIB_NAME_AW(GetRawInputDeviceInfo) +UINT WINAPI GetRawInputDeviceList(PRAWINPUTDEVICELIST,PUINT,UINT); BOOL WINAPI GetLayeredWindowAttributes(HWND,COLORREF*,BYTE*,DWORD*); HMENU WINAPI GetMenu(HWND); INT WINAPI GetMenuItemCount(HMENU); @@ -4831,9 +4891,10 @@ ATOM WINAPI RegisterClassW(const WNDCLASSW *); ATOM WINAPI RegisterClassExA(const WNDCLASSEXA *); ATOM WINAPI RegisterClassExW(const WNDCLASSEXW *); #define RegisterClassEx WINELIB_NAME_AW(RegisterClassEx) -UINT WINAPI RegisterClipboardFormatA(LPCSTR); -UINT WINAPI RegisterClipboardFormatW(LPCWSTR); +UINT WINAPI RegisterClipboardFormatA(LPCSTR); +UINT WINAPI RegisterClipboardFormatW(LPCWSTR); #define RegisterClipboardFormat WINELIB_NAME_AW(RegisterClipboardFormat) +BOOL WINAPI RegisterRawInputDevices(PRAWINPUTDEVICE,UINT,UINT); UINT WINAPI RegisterWindowMessageA(LPCSTR); UINT WINAPI RegisterWindowMessageW(LPCWSTR); #define RegisterWindowMessage WINELIB_NAME_AW(RegisterWindowMessage) diff --git a/programs/winecfg/audio.c b/programs/winecfg/audio.c index 5d5537f93d8..1ff5b80f05f 100644 --- a/programs/winecfg/audio.c +++ b/programs/winecfg/audio.c @@ -732,7 +732,8 @@ AudioDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) configureAudioDriver(hDlg); break; case IDC_AUDIO_TEST: - MessageBox(NULL, "Audio Test not implemented yet!", "Fixme", MB_OK | MB_ICONERROR); + if(!PlaySound(MAKEINTRESOURCE(IDW_TESTSOUND), NULL, SND_RESOURCE | SND_SYNC)) + MessageBox(NULL, "Audio test failed!", "Error", MB_OK | MB_ICONERROR); break; case IDC_AUDIO_CONTROL_PANEL: MessageBox(NULL, "Launching audio control panel not implemented yet!", "Fixme", MB_OK | MB_ICONERROR); diff --git a/programs/winecfg/idw_testsound.wav b/programs/winecfg/idw_testsound.wav new file mode 100644 index 0000000000000000000000000000000000000000..63574ae91ef8336b5a9723ff57f8d2c271327a8f GIT binary patch literal 12348 zcwX&VOK=?5bsd0o0#HdAGXQ0Ra;iApJ(QJfF#URz$leIk13TG8Xxd(;EV#1EBBrZS z+0k*5A}Bcll?`SFl$fkI{dy>|vWTZ&4^`e7{RVO+i&TV0QrTLFtFo1tlylB~4chCh zjh_GzdUNOAbI&>VzS;eQuYNV!YBavN{f(VJ{*&+C*l08w&Bjt=kTn`#`v!hkx!hQ8 zeERu6{?^`iFXP95{i8wA|~H|Tnyx7=R-$2>ooeKspg zGqtwV1-|5&nHp0RrmzOzmAS#^s5*S~k84SHBT2$2>cnc`?{!rWsYJzr@?Z2-;`u?p zrBv*B{-w`dTlryLWRIp0ndEr)bbM)yC)A>(xgj<!P%S~oyGo9vFM)$i{Rc8>WPH)!>;=a$LyMc=1e#nfdDDYJjD!w)U^6=yTd{pLh z^F9u?Rhcqe9Eo@((V5Nh4DbXdBmJ=P<<`qvSN&JRUW~(#VniDC87%|GPcaTx8yjJ_ z+5G;&{c1A*L>JX*Zuv1bi?m?2k>}GquTo=EQ;cmoO79KVTK*UM;cYLD)lOI43~_oK z#9^S4kOAY|9!eT2&-XSquZ=33eKK3qy+mJv1F;7d4sug(#NEBsSm>hM? zY?{sTJWWT#&DY-CO4KdCgFw{)hvDfb9&-@6)0vA{g{u44%h&D?&AiHrsm)Nid5Pj_ zVxuJD2xdG)YBFt((#h!H{#HkQI~@2o!ybZFNgp}r0K_OEW9GX;Zn~cLdZYPh^lVaC zAQ^|B&Hyq%0M+t^&<=1G z`i_|Eck#9Fh2gpiTfeuO|E(?-r|GmpkPEcl97iGp*7cv6=4GDSnJ$N;dr#K?{Kkg5 zc{L7`AVjMGbBH+XpzQ!{wBTMB&F!hMzqH=moP0VdZ2@$kgl1uoZAoq>QP=P2K%?JI zH&?w~q@i~+Owf2}JCrSu_G4G0KO(6h+r(RcX(>NDE;F2Lih0g(t6YvQq(?F%ePW7K zkH_Ozwz@Z?H@AVfPK|`tYrjzz&yK-y3+8~0SMXSV zAjy0H9FCxk(Pn9=k~kQ|@h;fMg&Qzr*Le|6NBypP9w?*TdhH6>6AU;1Bn5fSncXRY zfk$|r3=&74|1jSiZoL5px*4E5NT0|yauTQk;w0!2bci2^q4KxAt+oBh<9tyR3*^{J zxK_>;`n2v`hHPi)r*9pm=>p`p4I(&lsK3(KQ;+0w{CrIF^G$*4wpoDN@Dd##uBZ+q${$VaM&By?2NCpwT9oQVhUd=)oafAM!e zdiX4_s^g>VH01|a$dZYe5`N_a5X|ZL?cuO-*=XKPJc+vxMkV^$4X1q~< z8~UVzZn%7T?MpNBxUv-*P*bFi^L#NYw9SsRq*;^W%v7gGIdeC(sXnrl3I}D^jqoV`t|iFy4l(F z_xvF71Ze1GpQIlKNDAoA^W!c!uJu>nU%E4Vugr_5`mvr9aOWu+8C{5Ur#2VnEGJ`Q z@^X~!|NWNgy{K-59RRL>>wlXKl#ChXV}SI1qB%w`VsM7PzOl6Yf=Q z&U)&4&k45J3;;TPkm_`jzVIa6>Lt7Jb`TJ7L9ZJ`V7Lt&wh{Bpep{)lp6~lAZ2sN- zCzU?WPx3j$&sH-k)EH-hl&!0wL2kz8!DKW!9KO?vI{i+x3tsjpOsc1Nb_9A0A$w8M zQhtO)_gmqYHt&z-`h9fCC(w^)BU2th@lZ2+WKPqx7*8hv+}k>z=-Ku0=n`B@qIy@8 z(0|#J?$~Qb9$F8i*$Y`raCEl|&|PZWpM9*eg*k)L6|fnoSZ0rBdYVfm^SRdV4M%#I zA0OVEG+$6bqV^CenmTr+>(INzbh2Na541cG&eFL%zmF|F(x>P;Jjac`( z+wF~Y;LU^I3g2ihwf^9RhxrIu7|(yqCdsHGN5;JO*4r9A^6?PqEg#Jee)~Gq5`OSI zU3jjI2+aX_eJ?H#Yso=E2D1pN{T5NRL1ci`fI6+0)69Ht&s$ zIiKJ|n|Eg#jsr=-!y)B*fp7GKJpIAjqp_YCGkY>#+Fa|lyPpdY{?%W@19Z@d3B7J7 zL?QfI#ni=r_#5ST#;bXTrRtL)p>Nw@b=a!#wbhR|ALP^Q^fayPG2jFaMjzvuXVg!c zAbL)5arhRE{xOh;U@i5D4OrzzaC9~;_3>zCP zk9O1^v_+Uofa4;B%iHzP^dXYylL%lSk`_27>TXbrHxxZYD_mb*`eHSEe>OilA1@}5 zVw*pm!9~n1k?ZV)ObLY(>8ut$uymgDr;;5=(g5rK%~+?|@nmEs`CIA3zhArE4qpv= z4%bdtB8COZBahIF(eMQf-KEy2Z^F~U_h>I+UFRP-8Ng~ohP>9=(xZQ|8I}Gt7e{5Y zlCjOf2MBZlz@o=8I5t=;on1Hp23b&03d%OkGaMIY6SO3?Ft?+7n^!J(UuBjV=uJ2d zDlNkt_yJQHGjN9rT1gOAK=FlC(2NKegwUZsK0yIaS3X?N^7`;czxg1m3JXPsKM^}T zMdpADM9Rqq@PN0d?TVfsk291)10lwFxw0lYiWS65=MTnXJ<4Bs>4y4FoCGxGy{I41 zj54Q~g2aY_mr(mb=msJt-K#AQO+zRM7Ie^N6D}cWA;ep&dCyLZGYdPs0G5$TI95@L zjN{B>&I!bIr7?hrNN4h^I^5cSaF^yUp2m-f2Q#lBu+=AW=Bj3eX zMpIjIq%7)?Yo}2-r#MaFMD@|VE1T`z9S`0Mz)1QM8w`!t3FDylVamDQJ{_LVfm3Kf zupLt*iD{@0`5ey`kcJv#P-?I2pDv1XQ&qq%C=xluLoZBaoc$qYr_ywiUM(KE(k{37 zV7nUUnt>3&_|n-I8U`vbD@WtIYmJ@$06E=5B9UN;FcOdFgxqI<2sm`v_mayY$Y(N5$g>Q6VNXJ)D@2S$rUD=Bb?0GmhLHk! ztaxI@CX#wuXP4-s!A=?GFs z!6DOeE2>%KTt~>cq*CN_zq#GRTc0~5k|+su+uwx(1)v~E6T;@S>3e>=y)vvSJ1;7j z(ZW7pZXNy&%fo#VPR+(hMXE7WwBH!?2dbA46-;s>+EI(K5Cq2xOjs!79dlMKEH_C~ zJyy+%3R~ijlu9>ka)dm(d(HoPjAZoj+m)sPRFJY;@njr(}T#U%j&8369_!%5&anS}D(UwsM znPhfkj$Yt+oR99_*zWA89j5sg<0jVxbP`@b%rW5(8Q*(k7v~@YNCTiDXEV`e3eZu- zcsO(mN|26**KX{_gQ$b@MLl98a9Czf2ON!KIUAoY8E1t(LAzR)3X&lm5{7W_cEw$t zg}iVlGa9aWx8ms40CX3@ayq^@r-P=ns>|dY>`#AbW0?*2}#V>oSI7m z0vFk6G`idF?x240AcTObB(AkJ5=j;Bhodp7z@0Q(jeTpM76hH0awTJ(cgkeVn$@E> z^PHmrSG~O?2ADgdD88&&A&2g088?|~8cT0|`QXt<=2=ECGu|w_XurC#Ic-vCbDn&- z7QPA+jbIEq2vQOuEEJF&BY5kG%&vmaYd4n;(~t7^4aUNP0lQTznL4wsOK_;=f;iO^ zfEncjm^;u7*|kzn1|A0$XDP(8k>!w#gGa?P1k4c#38+NVw3Qt(Wev_8kHle9kkQ%! zdqzECdB7YGWO>Q)&24))zX=<)T1$8H56y>mA-ahMDQaS7LH-0Z@)5}B4fHkp zk4)#PC(Gg3^|e?D_`-Q+LLl>E!@r`uOz=l|?VnyVE^#`066csh*9#^*7LHowa1VPV{4tOSU*>oo|)SJ?}y_#hOL80leu^mHD zk~j{W3svGnC1?<->Updn(E-|Md{CZPDB#o72RT7<2LVCBfdq|+ z#|ZpD)k-A|==-hqoyq(e8qm_KagAFzuO_}Lt1-us0%;!YuZ25N4-uYT#^Id zsjJ(UOAEGJONaKEIfI^LT;UeBN@ed%XHD|w1r3+EMrV`Z@Y<4k^~HFwtpvLP*GJY^lotHLVv=;5eK zY?Nb0%}r;PzV+F?>-+bvU0Z(TPn+Dv`4~UKpra5LuU?`JevNm1rnK+6cmw6>1#%;S zkYNczX4~xq+#DEO+%iSAg$4n1{0m2orz$-gMv3QlLcl5E`renP%~puJu&NuLKVDTM za|Vb1;d!3gPjbwOr)iNRt0>sQaDPC9C|6Z{hLueVk~1q=*HrkA<0Si%L?v^&j61eg z2-b(`VWIf%xjVz9tadN_zw*Z#xy!~AV`o-BJUm*v-@ANcR}J<;af!0dm9Z@WEi+Tx zmjt{ab9KF#h+xk;e995oK+x}o3{H4XK>4F|1^%exk$-$QHo?3ET=#=CWIByFZS{Fs z;qedDZm9ZQkD1)^mySlCTCM*JO+GK?DLd$CDTaa0-7K<{TPH3x2n{$`ZRVMCYWO$$ zD)-0kn#0KDfec-AwaEAdxTY>iyef283T}Ln6}1tD;X59L+lDlMFq-IbF>aX6#0y`A ze^;+YdxS%Wb9t{%*A5dDvw;D+kQ!3wt>-vDe!g!IKf^zhNyzO?VxjBE(IC?zGqYd+ z)}=dS+WV?6Ls7&PB`-{vO(ke5OB{j?(!8;lt3L8V>mjn{t34b~x))ytJY* z*IeNtmt6ZVc<;u+x-@bjd2xF|4&Y6kq}{q%n{-C>*}6ju*&B$sW-xSl-L$D(?aE!L zp5@tOlD_bI^UXJ7FTSO`9kr)u&Pmh)J$OClBBFzd>vjw1)j$@blt08}IrROK(eZhK!Hv`NY|4H?sDQ&$D03OBL3qobc%(i|!(q6-rToUq zJO90y{p`b0IZ4TJX9R!{TdC(MxNnT7tN}tF( zojRA9Nl22wE#y+LywHw}uTLQQ9Q(P8CU=2FcaTqp>)YQ1)PS@e;NxzldtyPrfEa_~ z&^2fLi%wK-*k>jJx1!$2w|sRA554Qtd;1Xv_K+J@x6>25Qg>npDl4v8A`X4$3lOU3`|F{%axnV|jLb=< z;mhZiW|X|mIYN3s>MXZe@{@HJ%d$og=8>_E8O(J#8l}U-tvJSzizE!VB9)gM$nG(6 zh)-nw$b!l;Pk2UN^&u_72o>8W^p%+9=IXvV`-$B07lPk86SOdH=fqImsJ4(-u(>C5s3zD}f5v6!lKGeC|POOP=Ym9*%}> z^>S}Om5K%w^aO|l*zxG(hg!r~VT3L(J&}}rOcUp5o5qL znQ$}LdXsej&b3}gZuDchSyTgAX@%Uz;d_tjCcaYzwTp7sY!X_JyKrDnoIY0?=-&fl z|K}vliqoU~+3Xm-s>zazTw}nJ5tfX|RB;}Z4IW<@kkyl|EMW_G`-}I{@ZL%id*6_) zl^^%y7DR?}u9Cxgz3FCYKYq@9^ntQGcGN--C+m6DZnh3Gdv=oN|8BUQBsW(mH0>B3 z^kU^*Bd%sZEj=qW<^rOS_z1t$3|9`fc7h~|&>rj#-b@p4>}JrO%OGk>{i+QdG$%L;7TZ6=n5l6QELZzu;5Hqi?sni@?Uc?i-mL4rrsx7iBC@^ zhnFsQzsuDQulfUbfdu=)>H>2~D1s4R_}{1=hC;{A?pulo_Xk1CYhG>~9N(M$$5ATs zIL9Q%Meozqy*u(34^ zH%JBVxZDMiY@hjCgj%JVzty56gy8VnQMj>jduw}-Eg>uah&P83#e{w9Qs-_spZg+I z9xN%hK$K~ZeiC%OuGD&S>8F!nrayc-`($#IS9~Etl`hhpJ5Tb=RHVd`@VF+)tWyu` z41$@$5S>miK0@BclX7_Y(DR$|t?qW*k9zCscl}`3<8>5@Oas$Xr0OuK#Z9!Civ;;L z446~_;0A&V{MN?$msT6qaQNwi;V~2hi8(9F2`LZ71r5rifU!MwO~JJVU)jYuChTVwR%jG&IPa z&h!s-KEsdW;rRaMrSQw@_V2B!&emWHo!s5^{lRvv96~k;UnrIUUECDiZinl^26883 z{hWnd) return init_failed; + if (!data->hWnd) return init_not_supported; return init_success; } diff --git a/programs/wineconsole/wineconsole.c b/programs/wineconsole/wineconsole.c index 449cb646275..a78e07630ea 100644 --- a/programs/wineconsole/wineconsole.c +++ b/programs/wineconsole/wineconsole.c @@ -656,9 +656,18 @@ static struct inner_data* WINECON_Init(HINSTANCE hInst, DWORD pid, LPCWSTR appna WINE_TRACE("using hConOut %p\n", data->hConOut); /* filling data->curcfg from cfg */ - retry: switch ((*backend)(data)) { + case init_not_supported: + if (backend == WCCURSES_InitBackend) + { + if (WCUSER_InitBackend( data ) != init_success) break; + } + else if (backend == WCUSER_InitBackend) + { + if (WCCURSES_InitBackend( data ) != init_success) break; + } + /* fall through */ case init_success: WINECON_GetServerConfig(data); data->cells = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, @@ -684,16 +693,6 @@ static struct inner_data* WINECON_Init(HINSTANCE hInst, DWORD pid, LPCWSTR appna return data; case init_failed: break; - case init_not_supported: - if (backend == WCCURSES_InitBackend) - { - WINE_ERR("(n)curses was not found at configuration time.\n" - "If you want (n)curses support, please install relevant packages.\n" - "Now forcing user backend instead of (n)curses.\n"); - backend = WCUSER_InitBackend; - goto retry; - } - break; } error: @@ -768,7 +767,7 @@ static UINT WINECON_ParseOptions(const char* lpCmdLine, struct wc_init* wci) memset(wci, 0, sizeof(*wci)); wci->ptr = lpCmdLine; wci->mode = from_process_name; - wci->backend = WCCURSES_InitBackend; + wci->backend = WCUSER_InitBackend; for (;;) { @@ -792,6 +791,7 @@ static UINT WINECON_ParseOptions(const char* lpCmdLine, struct wc_init* wci) } else if (strncmp(wci->ptr + 10, "curses", 6) == 0) { + wci->backend = WCCURSES_InitBackend; wci->ptr += 16; } else diff --git a/server/Makefile.in b/server/Makefile.in index e6329d0e4ba..16ff2205b31 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -12,6 +12,7 @@ C_SRCS = \ change.c \ class.c \ clipboard.c \ + completion.c \ console.c \ context_alpha.c \ context_i386.c \ diff --git a/server/completion.c b/server/completion.c new file mode 100644 index 00000000000..f024b44a076 --- /dev/null +++ b/server/completion.c @@ -0,0 +1,242 @@ +/* + * Server-side IO completion ports implementation + * + * Copyright (C) 2007 Andrey Turkin + * + * 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 + * + */ + +/* FIXMEs: + * - built-in wait queues used which means: + * + threads are awaken FIFO and not LIFO as native does + * + "max concurrent active threads" parameter not used + * + completion handle is waitable, while native isn't + */ + +#include "config.h" +#include "wine/port.h" + +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" + +#include "wine/unicode.h" +#include "object.h" +#include "handle.h" +#include "request.h" + + +struct completion +{ + struct object obj; + struct list queue; + unsigned int depth; +}; + +static void completion_dump( struct object*, int ); +static void completion_destroy( struct object * ); +static int completion_signaled( struct object *obj, struct thread *thread ); + +static const struct object_ops completion_ops = +{ + sizeof(struct completion), /* size */ + completion_dump, /* dump */ + add_queue, /* add_queue */ + remove_queue, /* remove_queue */ + completion_signaled, /* signaled */ + no_satisfied, /* satisfied */ + no_signal, /* signal */ + no_get_fd, /* get_fd */ + no_map_access, /* map_access */ + no_lookup_name, /* lookup_name */ + no_open_file, /* open_file */ + no_close_handle, /* close_handle */ + completion_destroy /* destroy */ +}; + +struct comp_msg +{ + struct list queue_entry; + unsigned long ckey; + unsigned long cvalue; + unsigned long information; + unsigned int status; +}; + +static void completion_destroy( struct object *obj) +{ + struct completion *completion = (struct completion *) obj; + struct comp_msg *tmp, *next; + + LIST_FOR_EACH_ENTRY_SAFE( tmp, next, &completion->queue, struct comp_msg, queue_entry ) + { + free( tmp ); + } +} + +static void completion_dump( struct object *obj, int verbose ) +{ + struct completion *completion = (struct completion *) obj; + + assert( obj->ops == &completion_ops ); + fprintf( stderr, "Completion " ); + dump_object_name( &completion->obj ); + fprintf( stderr, " (%u packets pending)\n", completion->depth ); +} + +static int completion_signaled( struct object *obj, struct thread *thread ) +{ + struct completion *completion = (struct completion *)obj; + + return !list_empty( &completion->queue ); +} + +static struct completion *create_completion( struct directory *root, const struct unicode_str *name, unsigned int attr, unsigned int concurrent ) +{ + struct completion *completion; + + if ((completion = create_named_object_dir( root, name, attr, &completion_ops ))) + { + if (get_error() != STATUS_OBJECT_NAME_EXISTS) + { + list_init( &completion->queue ); + completion->depth = 0; + } + } + + return completion; +} + +static struct completion *get_completion_obj( struct process *process, obj_handle_t handle, unsigned int access ) +{ + return (struct completion *) get_handle_obj( process, handle, access, &completion_ops ); +} + +static void add_completion( struct completion *completion, unsigned long ckey, unsigned long cvalue, unsigned int status, unsigned long information ) +{ + struct comp_msg *msg = mem_alloc( sizeof( *msg ) ); + + if (!msg) + return; + + msg->ckey = ckey; + msg->cvalue = cvalue; + msg->status = status; + msg->information = information; + + list_add_tail( &completion->queue, &msg->queue_entry ); + completion->depth++; + wake_up( &completion->obj, 1 ); +} + +/* create a completion */ +DECL_HANDLER(create_completion) +{ + struct completion *completion; + struct unicode_str name; + struct directory *root = NULL; + + reply->handle = 0; + + get_req_unicode_str( &name ); + if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 ))) + return; + + if ( (completion = create_completion( root, &name, req->attributes, req->concurrent )) != NULL ) + { + reply->handle = alloc_handle( current->process, completion, req->access, req->attributes ); + release_object( completion ); + } + + if (root) release_object( root ); +} + +/* open a completion */ +DECL_HANDLER(open_completion) +{ + struct completion *completion; + struct unicode_str name; + struct directory *root = NULL; + + reply->handle = 0; + + get_req_unicode_str( &name ); + if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 ))) + return; + + if ( (completion = open_object_dir( root, &name, req->attributes, &completion_ops )) != NULL ) + { + reply->handle = alloc_handle( current->process, completion, req->access, req->attributes ); + release_object( completion ); + } + + if (root) release_object( root ); +} + + +/* add completion to completion port */ +DECL_HANDLER(add_completion) +{ + struct completion* completion = get_completion_obj( current->process, req->handle, IO_COMPLETION_MODIFY_STATE ); + + if (!completion) return; + + add_completion( completion, req->ckey, req->cvalue, req->status, req->information ); + + release_object( completion ); +} + +/* get completion from completion port */ +DECL_HANDLER(remove_completion) +{ + struct completion* completion = get_completion_obj( current->process, req->handle, IO_COMPLETION_MODIFY_STATE ); + struct list *entry; + struct comp_msg *msg; + + if (!completion) return; + + entry = list_head( &completion->queue ); + if (!entry) + set_error( STATUS_PENDING ); + else + { + list_remove( entry ); + completion->depth--; + msg = LIST_ENTRY( entry, struct comp_msg, queue_entry ); + reply->ckey = msg->ckey; + reply->cvalue = msg->cvalue; + reply->status = msg->status; + reply->information = msg->information; + free( msg ); + } + + release_object( completion ); +} + +/* get queue depth for completion port */ +DECL_HANDLER(query_completion) +{ + struct completion* completion = get_completion_obj( current->process, req->handle, IO_COMPLETION_QUERY_STATE ); + + if (!completion) return; + + reply->depth = completion->depth; + + release_object( completion ); +} diff --git a/server/protocol.def b/server/protocol.def index 6654658547c..3fedc27ee7b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2988,3 +2988,55 @@ enum message_type int group_count; /* the number of groups the token is a member of */ int privilege_count; /* the number of privileges the token has */ @END + + +/* Create I/O completion port */ +@REQ(create_completion) + unsigned int access; /* desired access to a port */ + unsigned int attributes; /* object attributes */ + unsigned int concurrent; /* max number of concurrent active threads */ + obj_handle_t rootdir; /* root directory */ + VARARG(filename,string); /* port name */ +@REPLY + obj_handle_t handle; /* port handle */ +@END + + +/* Open I/O completion port */ +@REQ(open_completion) + unsigned int access; /* desired access to a port */ + unsigned int attributes; /* object attributes */ + obj_handle_t rootdir; /* root directory */ + VARARG(filename,string); /* port name */ +@REPLY + obj_handle_t handle; /* port handle */ +@END + + +/* add completion to completion port */ +@REQ(add_completion) + obj_handle_t handle; /* port handle */ + unsigned long ckey; /* completion key */ + unsigned long cvalue; /* completion value */ + unsigned long information; /* IO_STATUS_BLOCK Information */ + unsigned int status; /* completion result */ +@END + + +/* get completion from completion port queue */ +@REQ(remove_completion) + obj_handle_t handle; /* port handle */ +@REPLY + unsigned long ckey; /* completion key */ + unsigned long cvalue; /* completion value */ + unsigned long information; /* IO_STATUS_BLOCK Information */ + unsigned int status; /* completion result */ +@END + + +/* get completion queue depth */ +@REQ(query_completion) + obj_handle_t handle; /* port handle */ +@REPLY + unsigned int depth; /* completion queue depth */ +@END diff --git a/server/request.h b/server/request.h index 32d7771e1d8..acdafaabedf 100644 --- a/server/request.h +++ b/server/request.h @@ -335,6 +335,11 @@ DECL_HANDLER(delete_device); DECL_HANDLER(get_next_device_request); DECL_HANDLER(make_process_system); DECL_HANDLER(get_token_statistics); +DECL_HANDLER(create_completion); +DECL_HANDLER(open_completion); +DECL_HANDLER(add_completion); +DECL_HANDLER(remove_completion); +DECL_HANDLER(query_completion); #ifdef WANT_REQUEST_HANDLERS @@ -566,6 +571,11 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_get_next_device_request, (req_handler)req_make_process_system, (req_handler)req_get_token_statistics, + (req_handler)req_create_completion, + (req_handler)req_open_completion, + (req_handler)req_add_completion, + (req_handler)req_remove_completion, + (req_handler)req_query_completion, }; #endif /* WANT_REQUEST_HANDLERS */ diff --git a/server/trace.c b/server/trace.c index 414b7c5bd45..5203dc29c4f 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3630,6 +3630,67 @@ static void dump_get_token_statistics_reply( const struct get_token_statistics_r fprintf( stderr, " privilege_count=%d", req->privilege_count ); } +static void dump_create_completion_request( const struct create_completion_request *req ) +{ + fprintf( stderr, " access=%08x,", req->access ); + fprintf( stderr, " attributes=%08x,", req->attributes ); + fprintf( stderr, " concurrent=%08x,", req->concurrent ); + fprintf( stderr, " rootdir=%p,", req->rootdir ); + fprintf( stderr, " filename=" ); + dump_varargs_string( cur_size ); +} + +static void dump_create_completion_reply( const struct create_completion_reply *req ) +{ + fprintf( stderr, " handle=%p", req->handle ); +} + +static void dump_open_completion_request( const struct open_completion_request *req ) +{ + fprintf( stderr, " access=%08x,", req->access ); + fprintf( stderr, " attributes=%08x,", req->attributes ); + fprintf( stderr, " rootdir=%p,", req->rootdir ); + fprintf( stderr, " filename=" ); + dump_varargs_string( cur_size ); +} + +static void dump_open_completion_reply( const struct open_completion_reply *req ) +{ + fprintf( stderr, " handle=%p", req->handle ); +} + +static void dump_add_completion_request( const struct add_completion_request *req ) +{ + fprintf( stderr, " handle=%p,", req->handle ); + fprintf( stderr, " ckey=%lx,", req->ckey ); + fprintf( stderr, " cvalue=%lx,", req->cvalue ); + fprintf( stderr, " information=%lx,", req->information ); + fprintf( stderr, " status=%08x", req->status ); +} + +static void dump_remove_completion_request( const struct remove_completion_request *req ) +{ + fprintf( stderr, " handle=%p", req->handle ); +} + +static void dump_remove_completion_reply( const struct remove_completion_reply *req ) +{ + fprintf( stderr, " ckey=%lx,", req->ckey ); + fprintf( stderr, " cvalue=%lx,", req->cvalue ); + fprintf( stderr, " information=%lx,", req->information ); + fprintf( stderr, " status=%08x", req->status ); +} + +static void dump_query_completion_request( const struct query_completion_request *req ) +{ + fprintf( stderr, " handle=%p", req->handle ); +} + +static void dump_query_completion_reply( const struct query_completion_reply *req ) +{ + fprintf( stderr, " depth=%08x", req->depth ); +} + static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_new_process_request, (dump_func)dump_get_new_process_info_request, @@ -3856,6 +3917,11 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_next_device_request_request, (dump_func)dump_make_process_system_request, (dump_func)dump_get_token_statistics_request, + (dump_func)dump_create_completion_request, + (dump_func)dump_open_completion_request, + (dump_func)dump_add_completion_request, + (dump_func)dump_remove_completion_request, + (dump_func)dump_query_completion_request, }; static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -4084,6 +4150,11 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_next_device_request_reply, (dump_func)dump_make_process_system_reply, (dump_func)dump_get_token_statistics_reply, + (dump_func)dump_create_completion_reply, + (dump_func)dump_open_completion_reply, + (dump_func)0, + (dump_func)dump_remove_completion_reply, + (dump_func)dump_query_completion_reply, }; static const char * const req_names[REQ_NB_REQUESTS] = { @@ -4312,6 +4383,11 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "get_next_device_request", "make_process_system", "get_token_statistics", + "create_completion", + "open_completion", + "add_completion", + "remove_completion", + "query_completion", }; static const struct diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 288de10ccf6..06ebd4f6bcf 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -575,7 +575,6 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure, const type_t *correlation_variable = NULL; unsigned char correlation_variable_type; unsigned char param_type = 0; - const char *param_type_string = NULL; size_t offset = 0; const var_t *var; @@ -602,46 +601,34 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure, case RPC_FC_CHAR: case RPC_FC_SMALL: param_type = RPC_FC_SMALL; - param_type_string = "FC_SMALL"; break; case RPC_FC_BYTE: case RPC_FC_USMALL: param_type = RPC_FC_USMALL; - param_type_string = "FC_USMALL"; break; case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_ENUM16: param_type = RPC_FC_SHORT; - param_type_string = "FC_SHORT"; break; case RPC_FC_USHORT: param_type = RPC_FC_USHORT; - param_type_string = "FC_USHORT"; break; case RPC_FC_LONG: case RPC_FC_ENUM32: param_type = RPC_FC_LONG; - param_type_string = "FC_LONG"; break; case RPC_FC_ULONG: param_type = RPC_FC_ULONG; - param_type_string = "FC_ULONG"; break; case RPC_FC_RP: case RPC_FC_UP: case RPC_FC_OP: case RPC_FC_FP: if (sizeof(void *) == 4) /* FIXME */ - { param_type = RPC_FC_LONG; - param_type_string = "FC_LONG"; - } else - { param_type = RPC_FC_HYPER; - param_type_string = "FC_HYPER"; - } break; default: error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n", @@ -649,7 +636,7 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure, } print_file(file, 2, "0x%x, /* Corr desc: %s */\n", - RPC_FC_NORMAL_CONFORMANCE | param_type, param_type_string); + RPC_FC_NORMAL_CONFORMANCE | param_type, string_of_type(param_type)); print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string); print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n", offset, offset); diff --git a/tools/wine.inf b/tools/wine.inf index b051aa0b613..cfad301d1cc 100644 --- a/tools/wine.inf +++ b/tools/wine.inf @@ -335,6 +335,28 @@ HKLM,System\CurrentControlSet\Control\VMM32Files,,,"" HKCU,Software\Wine\MSHTML,"GeckoUrl",,"http://source.winehq.org/winegecko.php" HKLM,HARDWARE\DEVICEMAP\PARALLEL PORTS,,,"" HKLM,HARDWARE\DEVICEMAP\SERIALCOMM,,,"" +; Some apps requires at least four subkeys of Active Setup\Installed Components +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{44BBA855-CC51-11CF-AAFA-00AA00B6015F},,2,"DirectDrawEx" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{44BBA855-CC51-11CF-AAFA-00AA00B6015F},"ComponentID",2,"DirectDrawEx" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{44BBA855-CC51-11CF-AAFA-00AA00B6015F},"IsInstalled",2,1 +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{44BBA855-CC51-11CF-AAFA-00AA00B6015F},"Locale",2,"*" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{44BBA855-CC51-11CF-AAFA-00AA00B6015F},"Version",2,"4,71,1113,0" + +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{7131646D-CD3C-40F4-97B9-CD9E4E6262EF},,2,".NET Framework" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{7131646D-CD3C-40F4-97B9-CD9E4E6262EF},"ComponentID",2,".NETFramework" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{7131646D-CD3C-40F4-97B9-CD9E4E6262EF},"Locale",2,"" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{7131646D-CD3C-40F4-97B9-CD9E4E6262EF},"Version",2,"2,0,50727,0" + +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{CB2F7EDD-9D1F-43C1-90FC-4F52EAE172A1},,2,".NET Framework" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{CB2F7EDD-9D1F-43C1-90FC-4F52EAE172A1},"ComponentID",2,".NETFramework" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{CB2F7EDD-9D1F-43C1-90FC-4F52EAE172A1},"Locale",2,"" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{CB2F7EDD-9D1F-43C1-90FC-4F52EAE172A1},"Version",2,"1,0,4322,1" + +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{de5aed00-a4bf-11d1-9948-00c04f98bbc9},,2,"HTML Help" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{de5aed00-a4bf-11d1-9948-00c04f98bbc9},"ComponentID",2,"HTMLHelp" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{de5aed00-a4bf-11d1-9948-00c04f98bbc9},"IsInstalled",2,1 +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{de5aed00-a4bf-11d1-9948-00c04f98bbc9},"Locale",2,"*" +HKLM,SOFTWARE\Microsoft\Active Setup\Installed Components\{de5aed00-a4bf-11d1-9948-00c04f98bbc9},"Version",2,"4,74,9273,0" [Nls] HKLM,System\CurrentControlSet\Control\Nls\Codepage,"37",,"" -- 2.11.4.GIT