From bf74be2a9a249e56c82fbffae17f01bbbfcae7f7 Mon Sep 17 00:00:00 2001 From: Jan Zerebecki Date: Fri, 29 Jun 2007 15:32:22 +0200 Subject: [PATCH] push aea352fc3df615e3f4b48daf6f897ea93ad1fffd --- dlls/advapi32/service.c | 73 ++++- dlls/advapi32/tests/service.c | 10 +- dlls/cabinet/fci.c | 6 +- dlls/comctl32/tests/comboex.c | 4 +- dlls/crypt32/msg.c | 248 ++++++++++++++- dlls/crypt32/tests/Makefile.in | 1 + dlls/crypt32/tests/msg.c | 471 +++++++++++++++++++++++++++++ dlls/dinput/device.c | 20 +- dlls/dinput/device_private.h | 2 + dlls/dinput/dinput_main.c | 72 +---- dlls/dinput/joystick_linux.c | 54 +--- dlls/dinput/joystick_linuxinput.c | 48 +-- dlls/dinput/keyboard.c | 59 +--- dlls/dinput/mouse.c | 49 +-- dlls/dsound/primary.c | 5 +- dlls/mshtml/conpoint.c | 98 +++--- dlls/mshtml/htmlbody.c | 14 + dlls/mshtml/htmldoc.c | 13 +- dlls/mshtml/mshtml_private.h | 37 ++- dlls/mshtml/persist.c | 2 +- dlls/mshtml/task.c | 6 +- dlls/msi/action.c | 21 +- dlls/msi/tests/package.c | 93 ++++++ dlls/ntdll/directory.c | 5 - dlls/ntdll/file.c | 12 - dlls/ntdll/thread.c | 2 +- dlls/ntdll/virtual.c | 4 +- dlls/ole32/compobj.c | 18 +- dlls/ole32/compobj_private.h | 4 +- dlls/pdh/pdh.spec | 14 +- dlls/pdh/pdh_main.c | 293 ++++++++++++++++++ dlls/riched20/Makefile.in | 2 +- dlls/riched20/editor.c | 59 ++++ dlls/riched20/editstr.h | 2 + dlls/shell32/shell32_Pt.rc | 38 +-- dlls/shell32/shelllink.c | 26 +- dlls/shell32/tests/shelllink.c | 93 ++++-- dlls/winealsa.drv/dsoutput.c | 113 ++++--- dlls/wined3d/device.c | 137 +++++++-- dlls/wined3d/glsl_shader.c | 56 ++++ dlls/wined3d/pixelshader.c | 2 +- dlls/wined3d/vertexshader.c | 2 +- dlls/wined3d/wined3d_private.h | 2 +- dlls/winemp3.acm/mpegl3.c | 2 + dlls/ws2_32/socket.c | 153 +++++----- dlls/ws2_32/tests/sock.c | 73 +++++ include/Makefile.in | 3 + include/dsdriver.h | 1 + include/pdh.h | 186 ++++++++++++ dlls/pdh/pdh_main.c => include/pdhmsg.h | 33 +- include/wincrypt.h | 12 + include/winperf.h | 65 ++++ libs/wpp/ppl.l | 27 +- programs/uninstaller/Ru.rc | 44 +++ programs/uninstaller/rsrc.rc | 1 + programs/winefile/splitpath.c | 14 +- programs/winefile/winefile.c | 64 ++-- programs/winemenubuilder/winemenubuilder.c | 172 ++++++----- tools/wine.inf | 1 + tools/wrc/parser.l | 74 +---- 60 files changed, 2382 insertions(+), 833 deletions(-) create mode 100644 dlls/crypt32/tests/msg.c create mode 100644 include/pdh.h copy dlls/pdh/pdh_main.c => include/pdhmsg.h (58%) create mode 100644 include/winperf.h create mode 100644 programs/uninstaller/Ru.rc diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index 09ab0deb4ee..731d668b8aa 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -240,6 +240,8 @@ static const WCHAR szDependOnService[] = { 'D','e','p','e','n','d','O','n','S','e','r','v','i','c','e',0}; static const WCHAR szObjectName[] = { 'O','b','j','e','c','t','N','a','m','e',0}; +static const WCHAR szTag[] = { + 'T','a','g',0}; struct reg_value { DWORD type; @@ -1849,6 +1851,11 @@ QueryServiceConfigW( SC_HANDLE hService, } hKey = hsvc->hkey; + /* TODO: Check which members are mandatory and what the registry types + * should be. This should of course also be tested when a service is + * created. + */ + /* calculate the size required first */ total = sizeof (QUERY_SERVICE_CONFIGW); @@ -1871,6 +1878,8 @@ QueryServiceConfigW( SC_HANDLE hService, r = RegQueryValueExW( hKey, szGroup, 0, &type, NULL, &sz ); if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) total += sz; + else + total += sizeof(WCHAR); sz = 0; r = RegQueryValueExW( hKey, szDependencies, 0, &type, NULL, &sz ); @@ -1883,11 +1892,15 @@ QueryServiceConfigW( SC_HANDLE hService, r = RegQueryValueExW( hKey, szObjectName, 0, &type, NULL, &sz ); if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) total += sz; + else + total += sizeof(WCHAR); sz = 0; r = RegQueryValueExW( hKey, szDisplayName, 0, &type, NULL, &sz ); if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) total += sz; + else + total += sizeof(WCHAR); *pcbBytesNeeded = total; @@ -1902,19 +1915,24 @@ QueryServiceConfigW( SC_HANDLE hService, sz = sizeof val; r = RegQueryValueExW( hKey, szType, 0, &type, (LPBYTE)&val, &sz ); - if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) ) + if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) ) lpServiceConfig->dwServiceType = val; sz = sizeof val; r = RegQueryValueExW( hKey, szStart, 0, &type, (LPBYTE)&val, &sz ); - if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) ) + if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) ) lpServiceConfig->dwStartType = val; sz = sizeof val; r = RegQueryValueExW( hKey, szError, 0, &type, (LPBYTE)&val, &sz ); - if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) ) + if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) ) lpServiceConfig->dwErrorControl = val; + sz = sizeof val; + r = RegQueryValueExW( hKey, szTag, 0, &type, (LPBYTE)&val, &sz ); + if( ( r == ERROR_SUCCESS ) && ( type == REG_DWORD ) ) + lpServiceConfig->dwTagId = val; + /* now do the strings */ p = (LPBYTE) &lpServiceConfig[1]; n = total - sizeof (QUERY_SERVICE_CONFIGW); @@ -1939,17 +1957,23 @@ QueryServiceConfigW( SC_HANDLE hService, sz = n; r = RegQueryValueExW( hKey, szGroup, 0, &type, p, &sz ); - if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) ) + lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p; + if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) { - lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p; p += sz; n -= sz; } + else + { + *(WCHAR *) p = 0; + p += sizeof(WCHAR); + n -= sizeof(WCHAR); + } sz = n; r = RegQueryValueExW( hKey, szDependencies, 0, &type, p, &sz ); lpServiceConfig->lpDependencies = (LPWSTR) p; - if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) ) + if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) { p += sz; n -= sz; @@ -1961,11 +1985,44 @@ QueryServiceConfigW( SC_HANDLE hService, n -= sizeof(WCHAR); } + sz = n; + r = RegQueryValueExW( hKey, szObjectName, 0, &type, p, &sz ); + lpServiceConfig->lpServiceStartName = (LPWSTR) p; + if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) + { + p += sz; + n -= sz; + } + else + { + *(WCHAR *) p = 0; + p += sizeof(WCHAR); + n -= sizeof(WCHAR); + } + + sz = n; + r = RegQueryValueExW( hKey, szDisplayName, 0, &type, p, &sz ); + lpServiceConfig->lpDisplayName = (LPWSTR) p; + if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) ) + { + p += sz; + n -= sz; + } + else + { + *(WCHAR *) p = 0; + p += sizeof(WCHAR); + n -= sizeof(WCHAR); + } + if( n < 0 ) ERR("Buffer overflow!\n"); - TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) ); - TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) ); + TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) ); + TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) ); + TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) ); + TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) ); + TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) ); return TRUE; } diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c index 7dde5f54036..206e4f05e62 100644 --- a/dlls/advapi32/tests/service.c +++ b/dlls/advapi32/tests/service.c @@ -116,6 +116,8 @@ static void test_sequence(void) "Expected ERROR_SUCCESS, ERROR_IO_PENDING or 0xdeadbeef, got %d\n", GetLastError()); ok(given == needed, "Expected the given (%d) and needed (%d) buffersizes to be equal\n", given, needed); } + ok(config->lpBinaryPathName && config->lpLoadOrderGroup && config->lpDependencies && config->lpServiceStartName && + config->lpDisplayName, "Expected all string struct members to be non-NULL\n"); ok(config->dwServiceType == (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS), "Expected SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS, got %d\n", config->dwServiceType); ok(config->dwStartType == SERVICE_DISABLED, "Expected SERVICE_DISABLED, got %d\n", config->dwStartType); @@ -125,11 +127,11 @@ static void test_sequence(void) ok(config->dwTagId == 0, "Expected 0, got %d\n", config->dwTagId); /* TODO: Show the double 0 terminated string */ todo_wine + { ok(!memcmp(config->lpDependencies, dependencies, sizeof(dependencies)), "Wrong string\n"); - if(config->lpServiceStartName) /* FIXME: Wine workaround, remove when fixed */ - ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName); - if(config->lpDisplayName) /* FIXME: Wine workaround, remove when fixed */ - ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName); + ok(!strcmp(config->lpServiceStartName, localsystem), "Expected 'LocalSystem', got '%s'\n", config->lpServiceStartName); + } + ok(!strcmp(config->lpDisplayName, displayname), "Expected '%s', got '%s'\n", displayname, config->lpDisplayName); SetLastError(0xdeadbeef); ret = DeleteService(svc_handle); diff --git a/dlls/cabinet/fci.c b/dlls/cabinet/fci.c index 112c06b1107..b5e6c9c23f6 100644 --- a/dlls/cabinet/fci.c +++ b/dlls/cabinet/fci.c @@ -173,7 +173,11 @@ HFCI __cdecl FCICreate( int err; PFCI_Int p_fci_internal; - if ((!perf) || (!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) || + if (!perf) { + SetLastError(ERROR_BAD_ARGUMENTS); + return NULL; + } + if ((!pfnalloc) || (!pfnfree) || (!pfnopen) || (!pfnread) || (!pfnwrite) || (!pfnclose) || (!pfnseek) || (!pfndelete) || (!pfnfcigtf) || (!pccab)) { perf->erfOper = FCIERR_NONE; diff --git a/dlls/comctl32/tests/comboex.c b/dlls/comctl32/tests/comboex.c index 8943d82bdd2..f4d8fc8103f 100644 --- a/dlls/comctl32/tests/comboex.c +++ b/dlls/comctl32/tests/comboex.c @@ -82,7 +82,7 @@ static void test_comboboxex(void) { out_of_range_item[] = {'O','u','t',' ','o','f',' ','R','a','n','g','e',' ','I','t','e','m',0}; /* Allocate space for result */ - textBuffer = malloc(MAX_CHARS); + textBuffer = HeapAlloc(GetProcessHeap(), 0, MAX_CHARS); /* Basic comboboxex test */ myHwnd = createComboEx(WS_BORDER | WS_VISIBLE | WS_CHILD | CBS_DROPDOWN); @@ -168,7 +168,7 @@ static void test_comboboxex(void) { /* Cleanup */ - free(textBuffer); + HeapFree(GetProcessHeap(), 0, textBuffer); } diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c index 2377ae28b42..4ac5cf09856 100644 --- a/dlls/crypt32/msg.c +++ b/dlls/crypt32/msg.c @@ -24,13 +24,207 @@ WINE_DEFAULT_DEBUG_CHANNEL(crypt); +/* Called when a message's ref count reaches zero. Free any message-specific + * data here. + */ +typedef void (*CryptMsgCloseFunc)(HCRYPTMSG msg); + +typedef BOOL (*CryptMsgGetParamFunc)(HCRYPTMSG hCryptMsg, DWORD dwParamType, + DWORD dwIndex, void *pvData, DWORD *pcbData); + +typedef BOOL (*CryptMsgUpdateFunc)(HCRYPTMSG hCryptMsg, const BYTE *pbData, + DWORD cbData, BOOL fFinal); + +typedef struct _CryptMsgBase +{ + LONG ref; + DWORD open_flags; + PCMSG_STREAM_INFO stream_info; + BOOL finalized; + CryptMsgCloseFunc close; + CryptMsgUpdateFunc update; + CryptMsgGetParamFunc get_param; +} CryptMsgBase; + +static inline void CryptMsgBase_Init(CryptMsgBase *msg, DWORD dwFlags, + PCMSG_STREAM_INFO pStreamInfo) +{ + msg->ref = 1; + msg->open_flags = dwFlags; + msg->stream_info = pStreamInfo; + msg->finalized = FALSE; +} + +typedef struct _CDataEncodeMsg +{ + CryptMsgBase base; + DWORD bare_content_len; + LPBYTE bare_content; +} CDataEncodeMsg; + +static const BYTE empty_data_content[] = { 0x04,0x00 }; + +static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg) +{ + CDataEncodeMsg *msg = (CDataEncodeMsg *)hCryptMsg; + + if (msg->bare_content != empty_data_content) + LocalFree(msg->bare_content); +} + +static BOOL CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData, + DWORD cbData, BOOL fFinal) +{ + CDataEncodeMsg *msg = (CDataEncodeMsg *)hCryptMsg; + BOOL ret = FALSE; + + if (msg->base.finalized) + SetLastError(CRYPT_E_MSG_ERROR); + else if (!fFinal) + { + if (msg->base.open_flags & CMSG_DETACHED_FLAG) + SetLastError(E_INVALIDARG); + else + SetLastError(CRYPT_E_MSG_ERROR); + } + else + { + msg->base.finalized = TRUE; + if (!cbData) + SetLastError(E_INVALIDARG); + else + { + CRYPT_DATA_BLOB blob = { cbData, (LPBYTE)pbData }; + + /* data messages don't allow non-final updates, don't bother + * checking whether data already exist, they can't. + */ + ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_OCTET_STRING, + &blob, CRYPT_ENCODE_ALLOC_FLAG, NULL, &msg->bare_content, + &msg->bare_content_len); + if (ret && msg->base.stream_info) + FIXME("stream info unimplemented\n"); + } + } + return ret; +} + +static BOOL CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, + DWORD dwIndex, void *pvData, DWORD *pcbData) +{ + CDataEncodeMsg *msg = (CDataEncodeMsg *)hCryptMsg; + BOOL ret = FALSE; + + switch (dwParamType) + { + case CMSG_CONTENT_PARAM: + { + CRYPT_CONTENT_INFO info; + char rsa_data[] = "1.2.840.113549.1.7.1"; + + info.pszObjId = rsa_data; + info.Content.cbData = msg->bare_content_len; + info.Content.pbData = msg->bare_content; + ret = CryptEncodeObject(X509_ASN_ENCODING, PKCS_CONTENT_INFO, &info, + pvData, pcbData); + break; + } + case CMSG_BARE_CONTENT_PARAM: + if (!pvData) + { + *pcbData = msg->bare_content_len; + ret = TRUE; + } + else if (*pcbData < msg->bare_content_len) + { + *pcbData = msg->bare_content_len; + SetLastError(ERROR_MORE_DATA); + } + else + { + *pcbData = msg->bare_content_len; + memcpy(pvData, msg->bare_content, msg->bare_content_len); + ret = TRUE; + } + break; + default: + SetLastError(CRYPT_E_INVALID_MSG_TYPE); + } + return ret; +} + +static HCRYPTMSG CDataEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo, + LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo) +{ + CDataEncodeMsg *msg; + + if (pvMsgEncodeInfo) + { + SetLastError(E_INVALIDARG); + return NULL; + } + msg = CryptMemAlloc(sizeof(CDataEncodeMsg)); + if (msg) + { + CryptMsgBase_Init((CryptMsgBase *)msg, dwFlags, pStreamInfo); + msg->base.close = CDataEncodeMsg_Close; + msg->base.update = CDataEncodeMsg_Update; + msg->base.get_param = CDataEncodeMsg_GetParam; + msg->bare_content_len = sizeof(empty_data_content); + msg->bare_content = (LPBYTE)empty_data_content; + } + return (HCRYPTMSG)msg; +} + +static inline const char *MSG_TYPE_STR(DWORD type) +{ + switch (type) + { +#define _x(x) case (x): return #x + _x(CMSG_DATA); + _x(CMSG_SIGNED); + _x(CMSG_ENVELOPED); + _x(CMSG_SIGNED_AND_ENVELOPED); + _x(CMSG_HASHED); + _x(CMSG_ENCRYPTED); +#undef _x + default: + return wine_dbg_sprintf("unknown (%d)", type); + } +} + HCRYPTMSG WINAPI CryptMsgOpenToEncode(DWORD dwMsgEncodingType, DWORD dwFlags, DWORD dwMsgType, const void *pvMsgEncodeInfo, LPSTR pszInnerContentObjID, PCMSG_STREAM_INFO pStreamInfo) { - FIXME("(%08x, %08x, %08x, %p, %s, %p): stub\n", dwMsgEncodingType, dwFlags, + HCRYPTMSG msg = NULL; + + TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType, dwFlags, dwMsgType, pvMsgEncodeInfo, debugstr_a(pszInnerContentObjID), pStreamInfo); - return (HCRYPTMSG)1; + + if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING) + { + SetLastError(E_INVALIDARG); + return NULL; + } + switch (dwMsgType) + { + case CMSG_DATA: + msg = CDataEncodeMsg_Open(dwFlags, pvMsgEncodeInfo, + pszInnerContentObjID, pStreamInfo); + break; + case CMSG_SIGNED: + case CMSG_ENVELOPED: + case CMSG_HASHED: + FIXME("unimplemented for type %s\n", MSG_TYPE_STR(dwMsgType)); + break; + case CMSG_SIGNED_AND_ENVELOPED: + case CMSG_ENCRYPTED: + /* defined but invalid, fall through */ + default: + SetLastError(CRYPT_E_INVALID_MSG_TYPE); + } + return msg; } HCRYPTMSG WINAPI CryptMsgOpenToDecode(DWORD dwMsgEncodingType, DWORD dwFlags, @@ -39,32 +233,68 @@ HCRYPTMSG WINAPI CryptMsgOpenToDecode(DWORD dwMsgEncodingType, DWORD dwFlags, { FIXME("(%08x, %08x, %08x, %08lx, %p, %p): stub\n", dwMsgEncodingType, dwFlags, dwMsgType, hCryptProv, pRecipientInfo, pStreamInfo); - return (HCRYPTMSG)2; + + if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType) != PKCS_7_ASN_ENCODING) + { + SetLastError(E_INVALIDARG); + return NULL; + } + return NULL; } HCRYPTMSG WINAPI CryptMsgDuplicate(HCRYPTMSG hCryptMsg) { - FIXME("(%p): stub\n", hCryptMsg); + TRACE("(%p)\n", hCryptMsg); + + if (hCryptMsg) + { + CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg; + + InterlockedIncrement(&msg->ref); + } return hCryptMsg; } BOOL WINAPI CryptMsgClose(HCRYPTMSG hCryptMsg) { - FIXME("(%p): stub\n", hCryptMsg); + TRACE("(%p)\n", hCryptMsg); + + if (hCryptMsg) + { + CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg; + + if (InterlockedDecrement(&msg->ref) == 0) + { + TRACE("freeing %p\n", msg); + if (msg->close) + msg->close(msg); + CryptMemFree(msg); + } + } return TRUE; } BOOL WINAPI CryptMsgUpdate(HCRYPTMSG hCryptMsg, const BYTE *pbData, DWORD cbData, BOOL fFinal) { - FIXME("(%p, %p, %d, %d): stub\n", hCryptMsg, pbData, cbData, fFinal); - return TRUE; + CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg; + BOOL ret = FALSE; + + TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal); + if (msg && msg->update) + ret = msg->update(hCryptMsg, pbData, cbData, fFinal); + return ret; } BOOL WINAPI CryptMsgGetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex, void *pvData, DWORD *pcbData) { - FIXME("(%p, %d, %d, %p, %p): stub\n", hCryptMsg, dwParamType, dwIndex, + CryptMsgBase *msg = (CryptMsgBase *)hCryptMsg; + BOOL ret = FALSE; + + TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg, dwParamType, dwIndex, pvData, pcbData); - return FALSE; + if (msg && msg->get_param) + ret = msg->get_param(hCryptMsg, dwParamType, dwIndex, pvData, pcbData); + return ret; } diff --git a/dlls/crypt32/tests/Makefile.in b/dlls/crypt32/tests/Makefile.in index b57244d8554..89d6df586d3 100644 --- a/dlls/crypt32/tests/Makefile.in +++ b/dlls/crypt32/tests/Makefile.in @@ -12,6 +12,7 @@ CTESTS = \ crl.c \ encode.c \ main.c \ + msg.c \ oid.c \ protectdata.c \ sip.c \ diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c new file mode 100644 index 00000000000..16ab7f65e66 --- /dev/null +++ b/dlls/crypt32/tests/msg.c @@ -0,0 +1,471 @@ +/* + * Unit test suite for crypt32.dll's CryptMsg 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 +#include +#include +#include +#include + +#include "wine/test.h" + +static void test_msg_open_to_encode(void) +{ + HCRYPTMSG msg; + + /* Crash + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, NULL, + NULL, NULL); + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, NULL, NULL, + NULL); + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, NULL, NULL, + NULL); + */ + + /* Bad encodings */ + SetLastError(0xdeadbeef); + msg = CryptMsgOpenToEncode(0, 0, 0, NULL, NULL, NULL); + ok(!msg && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %x\n", GetLastError()); + SetLastError(0xdeadbeef); + msg = CryptMsgOpenToEncode(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL); + ok(!msg && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %x\n", GetLastError()); + + /* Bad message types */ + SetLastError(0xdeadbeef); + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, 0, NULL, NULL, NULL); + ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE, + "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError()); + SetLastError(0xdeadbeef); + msg = CryptMsgOpenToEncode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0, + NULL, NULL, NULL); + ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE, + "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError()); + SetLastError(0xdeadbeef); + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, + CMSG_SIGNED_AND_ENVELOPED, NULL, NULL, NULL); + ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE, + "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError()); + SetLastError(0xdeadbeef); + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, NULL, + NULL, NULL); + ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE, + "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError()); +} + +static void test_msg_open_to_decode(void) +{ + HCRYPTMSG msg; + CMSG_STREAM_INFO streamInfo = { 0 }; + + SetLastError(0xdeadbeef); + msg = CryptMsgOpenToDecode(0, 0, 0, 0, NULL, NULL); + ok(!msg && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %x\n", GetLastError()); + + /* Bad encodings */ + SetLastError(0xdeadbeef); + msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, 0, 0, NULL, NULL); + ok(!msg && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %x\n", GetLastError()); + SetLastError(0xdeadbeef); + msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, CMSG_DATA, 0, NULL, NULL); + ok(!msg && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %x\n", GetLastError()); + + /* The message type can be explicit... */ + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL, + NULL); + todo_wine { + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + CryptMsgClose(msg); + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL, + NULL); + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + CryptMsgClose(msg); + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL, + NULL); + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + CryptMsgClose(msg); + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL, + NULL); + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + CryptMsgClose(msg); + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, + CMSG_SIGNED_AND_ENVELOPED, 0, NULL, NULL); + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + CryptMsgClose(msg); + /* or implicit.. */ + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL); + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + CryptMsgClose(msg); + /* or even invalid. */ + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL, + NULL); + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + CryptMsgClose(msg); + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL); + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + } + CryptMsgClose(msg); + + /* And even though the stream info parameter "must be set to NULL" for + * CMSG_HASHED, it's still accepted. + */ + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL, + &streamInfo); + todo_wine + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + CryptMsgClose(msg); +} + +static void test_msg_get_param(void) +{ + BOOL ret; + HCRYPTMSG msg; + DWORD size, i, value; + CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 }; + CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 }; + + /* Crash + ret = CryptMsgGetParam(NULL, 0, 0, NULL, NULL); + ret = CryptMsgGetParam(NULL, 0, 0, NULL, &size); + ret = CryptMsgGetParam(msg, 0, 0, NULL, NULL); + */ + + /* Decoded messages */ + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL); + todo_wine + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + /* For decoded messages, the type is always available */ + size = 0; + ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size); + todo_wine { + ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError()); + size = sizeof(value); + ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size); + ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError()); + /* For this (empty) message, the type isn't set */ + ok(value == 0, "Expected type 0, got %d\n", value); + } + CryptMsgClose(msg); + + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL, + NULL); + todo_wine + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + /* For explicitly typed messages, the type is known. */ + size = sizeof(value); + ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size); + todo_wine { + ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError()); + ok(value == CMSG_DATA, "Expected CMSG_DATA, got %d\n", value); + } + for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++) + { + size = 0; + ret = CryptMsgGetParam(msg, i, 0, NULL, &size); + ok(!ret, "Parameter %d: expected failure\n", i); + } + CryptMsgClose(msg); + + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL, + NULL); + todo_wine { + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + size = sizeof(value); + ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size); + ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError()); + ok(value == CMSG_ENVELOPED, "Expected CMSG_ENVELOPED, got %d\n", value); + } + for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++) + { + size = 0; + ret = CryptMsgGetParam(msg, i, 0, NULL, &size); + ok(!ret, "Parameter %d: expected failure\n", i); + } + CryptMsgClose(msg); + + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL, + NULL); + todo_wine { + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + size = sizeof(value); + ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size); + ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError()); + ok(value == CMSG_HASHED, "Expected CMSG_HASHED, got %d\n", value); + } + for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++) + { + size = 0; + ret = CryptMsgGetParam(msg, i, 0, NULL, &size); + ok(!ret, "Parameter %d: expected failure\n", i); + } + CryptMsgClose(msg); + + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL, + NULL); + todo_wine { + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + size = sizeof(value); + ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size); + ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError()); + ok(value == CMSG_SIGNED, "Expected CMSG_SIGNED, got %d\n", value); + } + for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++) + { + size = 0; + ret = CryptMsgGetParam(msg, i, 0, NULL, &size); + ok(!ret, "Parameter %d: expected failure\n", i); + } + CryptMsgClose(msg); + + /* Explicitly typed messages get their types set, even if they're invalid */ + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL, + NULL); + todo_wine { + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + size = sizeof(value); + ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size); + ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError()); + ok(value == CMSG_ENCRYPTED, "Expected CMSG_ENCRYPTED, got %d\n", value); + } + CryptMsgClose(msg); + + msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL); + todo_wine { + ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError()); + size = sizeof(value); + ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size); + ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError()); + ok(value == 1000, "Expected 1000, got %d\n", value); + } + CryptMsgClose(msg); +} + +static void test_msg_close(void) +{ + BOOL ret; + HCRYPTMSG msg; + + /* NULL succeeds.. */ + ret = CryptMsgClose(NULL); + ok(ret, "CryptMsgClose failed: %x\n", GetLastError()); + /* but an arbitrary pointer crashes. */ + if (0) + ret = CryptMsgClose((HCRYPTMSG)1); + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL, + NULL); + ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError()); + ret = CryptMsgClose(msg); + ok(ret, "CryptMsgClose failed: %x\n", GetLastError()); +} + +static void check_param(LPCSTR test, HCRYPTMSG msg, DWORD param, + const BYTE *expected, DWORD expectedSize) +{ + DWORD size; + LPBYTE buf; + BOOL ret; + + size = 0; + ret = CryptMsgGetParam(msg, param, 0, NULL, &size); + ok(ret, "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError()); + buf = HeapAlloc(GetProcessHeap(), 0, size); + ret = CryptMsgGetParam(msg, param, 0, buf, &size); + ok(ret, "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError()); + ok(size == expectedSize, "%s: expected size %d, got %d\n", test, + expectedSize, size); + if (size) + ok(!memcmp(buf, expected, size), "%s: unexpected data\n", test); + HeapFree(GetProcessHeap(), 0, buf); +} + +static void test_data_msg_open(void) +{ + HCRYPTMSG msg; + CMSG_HASHED_ENCODE_INFO hashInfo = { 0 }; + + /* The data message type takes no additional info */ + SetLastError(0xdeadbeef); + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, &hashInfo, + NULL, NULL); + ok(!msg && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %x\n", GetLastError()); + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL, + NULL); + ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError()); + CryptMsgClose(msg); +} + +static const BYTE msgData[] = { 1, 2, 3, 4 }; + +static void test_data_msg_update(void) +{ + HCRYPTMSG msg; + BOOL ret; + + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL, + NULL); + /* Can't update a message that wasn't opened detached with final = FALSE */ + SetLastError(0xdeadbeef); + ret = CryptMsgUpdate(msg, NULL, 0, FALSE); + ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR, + "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError()); + /* Updating it with final = TRUE succeeds */ + ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); + ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError()); + /* Any subsequent update will fail, as the last was final */ + SetLastError(0xdeadbeef); + ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); + ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR, + "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError()); + CryptMsgClose(msg); + + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL, + NULL); + /* Can't update a message with no data */ + SetLastError(0xdeadbeef); + ret = CryptMsgUpdate(msg, NULL, 0, TRUE); + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %x\n", GetLastError()); + /* Curiously, a valid update will now fail as well, presumably because of + * the last (invalid, but final) update. + */ + ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); + ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR, + "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError()); + CryptMsgClose(msg); + + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG, + CMSG_DATA, NULL, NULL, NULL); + /* Dont appear to be able to update CMSG-DATA with non-final updates */ + SetLastError(0xdeadbeef); + ret = CryptMsgUpdate(msg, NULL, 0, FALSE); + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %x\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE); + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %x\n", GetLastError()); + ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); + ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError()); + CryptMsgClose(msg); +} + +static void test_data_msg_get_param(void) +{ + HCRYPTMSG msg; + DWORD size; + BOOL ret; + + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL, + NULL); + + /* Content and bare content are always gettable */ + size = 0; + ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size); + ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError()); + size = 0; + ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size); + ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError()); + /* But for this type of message, the signer and hash aren't applicable, + * and the type isn't available. + */ + size = 0; + SetLastError(0xdeadbeef); + ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size); + ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE, + "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError()); + SetLastError(0xdeadbeef); + ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size); + ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE, + "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError()); + ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size); + ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE, + "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError()); + + CryptMsgClose(msg); +} + +static const BYTE dataEmptyBareContent[] = { 0x04,0x00 }; +static const BYTE dataEmptyContent[] = { +0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02, +0x04,0x00 }; +static const BYTE dataBareContent[] = { 0x04,0x04,0x01,0x02,0x03,0x04 }; +static const BYTE dataContent[] = { +0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06, +0x04,0x04,0x01,0x02,0x03,0x04 }; + +static void test_data_msg_encoding(void) +{ + HCRYPTMSG msg; + BOOL ret; + + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL, + NULL); + check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM, + dataEmptyBareContent, sizeof(dataEmptyBareContent)); + check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent, + sizeof(dataEmptyContent)); + ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); + ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError()); + check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM, + dataBareContent, sizeof(dataBareContent)); + check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent, + sizeof(dataContent)); + CryptMsgClose(msg); + /* Same test, but with CMSG_BARE_CONTENT_FLAG set */ + msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG, + CMSG_DATA, NULL, NULL, NULL); + check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM, + dataEmptyBareContent, sizeof(dataEmptyBareContent)); + check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent, + sizeof(dataEmptyContent)); + ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); + ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError()); + check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM, + dataBareContent, sizeof(dataBareContent)); + check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent, + sizeof(dataContent)); + CryptMsgClose(msg); +} + +static void test_data_msg(void) +{ + test_data_msg_open(); + test_data_msg_update(); + test_data_msg_get_param(); + test_data_msg_encoding(); +} + +START_TEST(msg) +{ + /* Basic parameter checking tests */ + test_msg_open_to_encode(); + test_msg_open_to_decode(); + test_msg_get_param(); + test_msg_close(); + + /* Message-type specific tests */ + test_data_msg(); +} diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index b8fc781b8a5..35bf11704d5 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -677,8 +677,21 @@ ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface) ref = InterlockedDecrement(&(This->ref)); if (ref) return ref; - DeleteCriticalSection(&This->crit); + IDirectInputDevice_Unacquire(iface); + /* Reset the FF state, free all effects, etc */ + IDirectInputDevice8_SendForceFeedbackCommand(iface, DISFFC_RESET); + HeapFree(GetProcessHeap(), 0, This->data_queue); + + /* Free data format */ + HeapFree(GetProcessHeap(), 0, This->data_format.wine_df->rgodf); + HeapFree(GetProcessHeap(), 0, This->data_format.wine_df); + release_DataFormat(&This->data_format); + + IDirectInput_Release((LPDIRECTINPUTDEVICE8A)This->dinput); + This->crit.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->crit); + HeapFree(GetProcessHeap(), 0, This); return DI_OK; @@ -1173,9 +1186,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand( LPDIRECTINPUTDEVICE8A iface, DWORD dwFlags) { - FIXME("(this=%p,0x%08x): stub!\n", - iface, dwFlags); - return DI_OK; + TRACE("(%p) 0x%08x:\n", iface, dwFlags); + return DI_NOEFFECT; } HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects( diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 4af99cc6645..6295d6c26c2 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -25,6 +25,7 @@ #include "windef.h" #include "winbase.h" #include "dinput.h" +#include "dinput_private.h" typedef struct { @@ -53,6 +54,7 @@ struct IDirectInputDevice2AImpl LONG ref; GUID guid; CRITICAL_SECTION crit; + IDirectInputImpl *dinput; HANDLE hEvent; DWORD dwCoopLevel; HWND win; diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 402855e5217..28718fa6808 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -297,62 +297,6 @@ static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, RE return E_FAIL; } -static HRESULT WINAPI IDirectInputAImpl_CreateDevice( - LPDIRECTINPUT7A iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev, - LPUNKNOWN punk -) { - IDirectInputImpl *This = (IDirectInputImpl *)iface; - HRESULT ret_value = DIERR_DEVICENOTREG; - int i; - - TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk); - - if (pdev == NULL) { - WARN("invalid pointer: pdev == NULL\n"); - return E_POINTER; - } - - if (rguid == NULL) { - WARN("invalid pointer: rguid == NULL\n"); - return E_POINTER; - } - - /* Loop on all the devices to see if anyone matches the given GUID */ - for (i = 0; i < NB_DINPUT_DEVICES; i++) { - HRESULT ret; - if (!dinput_devices[i]->create_deviceA) continue; - if ((ret = dinput_devices[i]->create_deviceA(This, rguid, NULL, pdev)) == DI_OK) - return DI_OK; - - if (ret == DIERR_NOINTERFACE) - ret_value = DIERR_NOINTERFACE; - } - - return ret_value; -} - -static HRESULT WINAPI IDirectInputWImpl_CreateDevice(LPDIRECTINPUT7W iface, - REFGUID rguid, LPDIRECTINPUTDEVICEW* pdev, LPUNKNOWN punk) { - IDirectInputImpl *This = (IDirectInputImpl *)iface; - HRESULT ret_value = DIERR_DEVICENOTREG; - int i; - - TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk); - - /* Loop on all the devices to see if anyone matches the given GUID */ - for (i = 0; i < NB_DINPUT_DEVICES; i++) { - HRESULT ret; - if (!dinput_devices[i]->create_deviceW) continue; - if ((ret = dinput_devices[i]->create_deviceW(This, rguid, NULL, pdev)) == DI_OK) - return DI_OK; - - if (ret == DIERR_NOINTERFACE) - ret_value = DIERR_NOINTERFACE; - } - - return ret_value; -} - static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTANCE hinst, DWORD x) { TRACE("(this=%p,%p,%x)\n",iface, hinst, x); @@ -406,6 +350,8 @@ static HRESULT WINAPI IDirectInput7AImpl_CreateDeviceEx(LPDIRECTINPUT7A iface, R TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter); + if (!rguid || !pvOut) return E_POINTER; + /* Loop on all the devices to see if anyone matches the given GUID */ for (i = 0; i < NB_DINPUT_DEVICES; i++) { HRESULT ret; @@ -429,6 +375,8 @@ static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, R TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter); + if (!rguid || !pvOut) return E_POINTER; + /* Loop on all the devices to see if anyone matches the given GUID */ for (i = 0; i < NB_DINPUT_DEVICES; i++) { HRESULT ret; @@ -443,6 +391,18 @@ static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, R return ret_value; } +static HRESULT WINAPI IDirectInputAImpl_CreateDevice(LPDIRECTINPUT7A iface, REFGUID rguid, + LPDIRECTINPUTDEVICEA* pdev, LPUNKNOWN punk) +{ + return IDirectInput7AImpl_CreateDeviceEx(iface, rguid, NULL, (LPVOID*)pdev, punk); +} + +static HRESULT WINAPI IDirectInputWImpl_CreateDevice(LPDIRECTINPUT7W iface, REFGUID rguid, + LPDIRECTINPUTDEVICEW* pdev, LPUNKNOWN punk) +{ + return IDirectInput7WImpl_CreateDeviceEx(iface, rguid, NULL, (LPVOID*)pdev, punk); +} + static HRESULT WINAPI IDirectInput8AImpl_QueryInterface(LPDIRECTINPUT8A iface, REFIID riid, LPVOID *ppobj) { IDirectInputImpl *This = (IDirectInputImpl *)iface; diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c index 1eafcc7a311..57f1d7a31db 100644 --- a/dlls/dinput/joystick_linux.c +++ b/dlls/dinput/joystick_linux.c @@ -97,9 +97,6 @@ struct JoystickImpl char dev[32]; - /* The 'parent' DInput */ - IDirectInputImpl *dinput; - /* joystick private */ int joyfd; DIJOYSTATE2 js; /* wine data */ @@ -468,7 +465,7 @@ static HRESULT alloc_device(REFGUID rguid, const void *jvt, IDirectInputImpl *di newDevice->base.lpVtbl = jvt; newDevice->base.ref = 1; - newDevice->dinput = dinput; + newDevice->base.dinput = dinput; CopyMemory(&newDevice->base.guid, rguid, sizeof(*rguid)); InitializeCriticalSection(&newDevice->base.crit); newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit"); @@ -531,11 +528,11 @@ static HRESULT alloc_device(REFGUID rguid, const void *jvt, IDirectInputImpl *di newDevice->props[i].lSaturation = 0; } - IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->dinput); + IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->base.dinput); newDevice->devcaps.dwSize = sizeof(newDevice->devcaps); newDevice->devcaps.dwFlags = DIDC_ATTACHED; - if (newDevice->dinput->dwVersion >= 0x0800) + if (newDevice->base.dinput->dwVersion >= 0x0800) newDevice->devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); else newDevice->devcaps.dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); @@ -635,45 +632,6 @@ const struct dinput_device joystick_linux_device = { }; /****************************************************************************** - * Joystick - */ -static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE8A iface) -{ - JoystickImpl *This = (JoystickImpl *)iface; - ULONG ref; - - ref = InterlockedDecrement(&This->base.ref); - if (ref) - return ref; - - IDirectInputDevice_Unacquire(iface); - - /* Free the device name */ - HeapFree(GetProcessHeap(),0,This->name); - - /* Free the axis map */ - HeapFree(GetProcessHeap(),0,This->axis_map); - - /* Free the data queue */ - HeapFree(GetProcessHeap(), 0, This->base.data_queue); - - /* Free the properties */ - HeapFree(GetProcessHeap(), 0, This->props); - - /* release the data transform filter */ - HeapFree(GetProcessHeap(), 0, This->base.data_format.wine_df->rgodf); - HeapFree(GetProcessHeap(), 0, This->base.data_format.wine_df); - release_DataFormat(&This->base.data_format); - - This->base.crit.DebugInfo->Spare[0] = 0; - IDirectInput_Release((LPDIRECTINPUTDEVICE8A)This->dinput); - DeleteCriticalSection(&This->base.crit); - - HeapFree(GetProcessHeap(),0,This); - return 0; -} - -/****************************************************************************** * Acquire : gets exclusive control of the joystick */ static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) @@ -871,7 +829,7 @@ static void joy_polldev(JoystickImpl *This) { if (inst_id >= 0) queue_event((LPDIRECTINPUTDEVICE8A)This, id_to_offset(&This->base.data_format, inst_id), - value, jse.time, This->dinput->evsequence++); + value, jse.time, This->base.dinput->evsequence++); } } @@ -1217,7 +1175,7 @@ static const IDirectInputDevice8AVtbl JoystickAvt = { IDirectInputDevice2AImpl_QueryInterface, IDirectInputDevice2AImpl_AddRef, - JoystickAImpl_Release, + IDirectInputDevice2AImpl_Release, JoystickAImpl_GetCapabilities, IDirectInputDevice2AImpl_EnumObjects, JoystickAImpl_GetProperty, @@ -1259,7 +1217,7 @@ static const IDirectInputDevice8WVtbl SysJoystickWvt = { IDirectInputDevice2WImpl_QueryInterface, XCAST(AddRef)IDirectInputDevice2AImpl_AddRef, - XCAST(Release)JoystickAImpl_Release, + XCAST(Release)IDirectInputDevice2AImpl_Release, XCAST(GetCapabilities)JoystickAImpl_GetCapabilities, IDirectInputDevice2WImpl_EnumObjects, XCAST(GetProperty)JoystickAImpl_GetProperty, diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c index b41145d5cf4..6a8dd447319 100644 --- a/dlls/dinput/joystick_linuxinput.c +++ b/dlls/dinput/joystick_linuxinput.c @@ -131,9 +131,6 @@ struct JoystickImpl struct JoyDev *joydev; - /* The 'parent' DInput */ - IDirectInputImpl *dinput; - /* joystick private */ int joyfd; @@ -367,7 +364,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm InitializeCriticalSection(&newDevice->base.crit); newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit"); newDevice->joyfd = -1; - newDevice->dinput = dinput; + newDevice->base.dinput = dinput; newDevice->joydev = joydev; #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION newDevice->ff_state = FF_STATUS_STOPPED; @@ -423,7 +420,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm fake_current_js_state(newDevice); newDevice->base.data_format.wine_df = df; - IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->dinput); + IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->base.dinput); return newDevice; failed: @@ -505,39 +502,6 @@ const struct dinput_device joystick_linuxinput_device = { }; /****************************************************************************** - * Joystick - */ -static ULONG WINAPI JoystickAImpl_Release(LPDIRECTINPUTDEVICE8A iface) -{ - JoystickImpl *This = (JoystickImpl *)iface; - ULONG ref; - - ref = InterlockedDecrement(&This->base.ref); - if (ref) - return ref; - - IDirectInputDevice_Unacquire(iface); - - /* Reset the FF state, free all effects, etc */ - IDirectInputDevice8_SendForceFeedbackCommand(iface, DISFFC_RESET); - - /* Free the data queue */ - HeapFree(GetProcessHeap(), 0, This->base.data_queue); - - /* release the data transform filter */ - HeapFree(GetProcessHeap(), 0, This->base.data_format.wine_df->rgodf); - HeapFree(GetProcessHeap(), 0, This->base.data_format.wine_df); - release_DataFormat(&This->base.data_format); - - IDirectInput_Release((LPDIRECTINPUTDEVICE8A)This->dinput); - This->base.crit.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->base.crit); - - HeapFree(GetProcessHeap(),0,This); - return 0; -} - -/****************************************************************************** * Acquire : gets exclusive control of the joystick */ static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) @@ -753,7 +717,7 @@ static void joy_polldev(JoystickImpl *This) if (inst_id >= 0) queue_event((LPDIRECTINPUTDEVICE8A)This, id_to_offset(&This->base.data_format, inst_id), - value, ie.time.tv_usec, This->dinput->evsequence++); + value, ie.time.tv_usec, This->base.dinput->evsequence++); } } @@ -873,7 +837,7 @@ static HRESULT WINAPI JoystickAImpl_GetCapabilities( } lpDIDevCaps->dwFlags = DIDC_ATTACHED; - if (This->dinput->dwVersion >= 0x0800) + if (This->base.dinput->dwVersion >= 0x0800) lpDIDevCaps->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8); else lpDIDevCaps->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8); @@ -1328,7 +1292,7 @@ static const IDirectInputDevice8AVtbl JoystickAvt = { IDirectInputDevice2AImpl_QueryInterface, IDirectInputDevice2AImpl_AddRef, - JoystickAImpl_Release, + IDirectInputDevice2AImpl_Release, JoystickAImpl_GetCapabilities, IDirectInputDevice2AImpl_EnumObjects, JoystickAImpl_GetProperty, @@ -1370,7 +1334,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt = { IDirectInputDevice2WImpl_QueryInterface, XCAST(AddRef)IDirectInputDevice2AImpl_AddRef, - XCAST(Release)JoystickAImpl_Release, + XCAST(Release)IDirectInputDevice2AImpl_Release, XCAST(GetCapabilities)JoystickAImpl_GetCapabilities, IDirectInputDevice2WImpl_EnumObjects, XCAST(GetProperty)JoystickAImpl_GetProperty, diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c index df117825110..ad44023f586 100644 --- a/dlls/dinput/keyboard.c +++ b/dlls/dinput/keyboard.c @@ -47,8 +47,7 @@ typedef struct SysKeyboardImpl SysKeyboardImpl; struct SysKeyboardImpl { struct IDirectInputDevice2AImpl base; - - IDirectInputImpl* dinput; + BYTE DInputKeyState[WINE_DINPUT_KEYBOARD_MAX_KEYS]; }; static SysKeyboardImpl* current_lock = NULL; @@ -59,8 +58,6 @@ static SysKeyboardImpl* current_lock = NULL; * but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason. */ -static BYTE DInputKeyState[WINE_DINPUT_KEYBOARD_MAX_KEYS]; /* array for 'GetDeviceState' */ - static LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam ) { SysKeyboardImpl *This = (SysKeyboardImpl *)current_lock; @@ -79,15 +76,15 @@ static LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam new_diks = hook->flags & LLKHF_UP ? 0 : 0x80; /* returns now if key event already known */ - if (new_diks == DInputKeyState[dik_code]) + if (new_diks == This->DInputKeyState[dik_code]) return CallNextHookEx(0, code, wparam, lparam); - DInputKeyState[dik_code] = new_diks; - TRACE(" setting %02X to %02X\n", dik_code, DInputKeyState[dik_code]); + This->DInputKeyState[dik_code] = new_diks; + TRACE(" setting %02X to %02X\n", dik_code, This->DInputKeyState[dik_code]); dik_code = id_to_offset(&This->base.data_format, DIDFT_MAKEINSTANCE(dik_code) | DIDFT_PSHBUTTON); EnterCriticalSection(&This->base.crit); - queue_event((LPDIRECTINPUTDEVICE8A)This, dik_code, new_diks, hook->time, This->dinput->evsequence++); + queue_event((LPDIRECTINPUTDEVICE8A)This, dik_code, new_diks, hook->time, This->base.dinput->evsequence++); LeaveCriticalSection(&This->base.crit); return CallNextHookEx(0, code, wparam, lparam); @@ -194,7 +191,7 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, const void *kvt, IDirectInpu newDevice->base.lpVtbl = kvt; newDevice->base.ref = 1; memcpy(&newDevice->base.guid, rguid, sizeof(*rguid)); - newDevice->dinput = dinput; + newDevice->base.dinput = dinput; InitializeCriticalSection(&newDevice->base.crit); newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit"); @@ -216,7 +213,7 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, const void *kvt, IDirectInpu df->dwNumObjs = idx; newDevice->base.data_format.wine_df = df; - IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->dinput); + IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->base.dinput); return newDevice; failed: @@ -273,31 +270,6 @@ const struct dinput_device keyboard_device = { keyboarddev_create_deviceW }; -static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface) -{ - SysKeyboardImpl *This = (SysKeyboardImpl *)iface; - ULONG ref; - - ref = InterlockedDecrement(&This->base.ref); - if (ref) return ref; - - IDirectInputDevice_Unacquire(iface); - - HeapFree(GetProcessHeap(), 0, This->base.data_queue); - - /* Free data format */ - HeapFree(GetProcessHeap(), 0, This->base.data_format.wine_df->rgodf); - HeapFree(GetProcessHeap(), 0, This->base.data_format.wine_df); - release_DataFormat(&This->base.data_format); - - IDirectInput_Release((LPDIRECTINPUTDEVICE8A)This->dinput); - This->base.crit.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->base.crit); - HeapFree(GetProcessHeap(), 0, This); - - return DI_OK; -} - static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState( LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr ) @@ -315,13 +287,12 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState( if (TRACE_ON(dinput)) { int i; for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) { - if (DInputKeyState[i] != 0x00) { - TRACE(" - %02X: %02x\n", i, DInputKeyState[i]); - } + if (This->DInputKeyState[i] != 0x00) + TRACE(" - %02X: %02x\n", i, This->DInputKeyState[i]); } } - memcpy(ptr, DInputKeyState, WINE_DINPUT_KEYBOARD_MAX_KEYS); + memcpy(ptr, This->DInputKeyState, WINE_DINPUT_KEYBOARD_MAX_KEYS); LeaveCriticalSection(&This->base.crit); return DI_OK; @@ -388,7 +359,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities( devcaps.dwSize = lpDIDevCaps->dwSize; devcaps.dwFlags = DIDC_ATTACHED; - if (This->dinput->dwVersion >= 0x0800) + if (This->base.dinput->dwVersion >= 0x0800) devcaps.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8); else devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8); @@ -465,7 +436,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo( return DI_OK; } - fill_keyboard_dideviceinstanceA(pdidi, This->dinput->dwVersion); + fill_keyboard_dideviceinstanceA(pdidi, This->base.dinput->dwVersion); return DI_OK; } @@ -480,7 +451,7 @@ static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface return DI_OK; } - fill_keyboard_dideviceinstanceW(pdidi, This->dinput->dwVersion); + fill_keyboard_dideviceinstanceW(pdidi, This->base.dinput->dwVersion); return DI_OK; } @@ -489,7 +460,7 @@ static const IDirectInputDevice8AVtbl SysKeyboardAvt = { IDirectInputDevice2AImpl_QueryInterface, IDirectInputDevice2AImpl_AddRef, - SysKeyboardAImpl_Release, + IDirectInputDevice2AImpl_Release, SysKeyboardAImpl_GetCapabilities, IDirectInputDevice2AImpl_EnumObjects, IDirectInputDevice2AImpl_GetProperty, @@ -531,7 +502,7 @@ static const IDirectInputDevice8WVtbl SysKeyboardWvt = { IDirectInputDevice2WImpl_QueryInterface, XCAST(AddRef)IDirectInputDevice2AImpl_AddRef, - XCAST(Release)SysKeyboardAImpl_Release, + XCAST(Release)IDirectInputDevice2AImpl_Release, XCAST(GetCapabilities)SysKeyboardAImpl_GetCapabilities, IDirectInputDevice2WImpl_EnumObjects, XCAST(GetProperty)IDirectInputDevice2AImpl_GetProperty, diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c index ea551ef940b..3c80e7e47f8 100644 --- a/dlls/dinput/mouse.c +++ b/dlls/dinput/mouse.c @@ -54,8 +54,6 @@ struct SysMouseImpl { struct IDirectInputDevice2AImpl base; - IDirectInputImpl *dinput; - /* SysMouseAImpl */ /* These are used in case of relative -> absolute transitions */ POINT org_coords; @@ -178,7 +176,7 @@ static SysMouseImpl *alloc_device(REFGUID rguid, const void *mvt, IDirectInputIm memcpy(&newDevice->base.guid, rguid, sizeof(*rguid)); InitializeCriticalSection(&newDevice->base.crit); newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysMouseImpl*->base.crit"); - newDevice->dinput = dinput; + newDevice->base.dinput = dinput; /* Create copy of default data format */ if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIMouse2.dwSize))) goto failed; @@ -194,7 +192,7 @@ static SysMouseImpl *alloc_device(REFGUID rguid, const void *mvt, IDirectInputIm df->rgodf[i].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON; newDevice->base.data_format.wine_df = df; - IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->dinput); + IDirectInput_AddRef((LPDIRECTINPUTDEVICE8A)newDevice->base.dinput); return newDevice; failed: @@ -256,35 +254,6 @@ const struct dinput_device mouse_device = { * SysMouseA (DInput Mouse support) */ -/****************************************************************************** - * Release : release the mouse buffer. - */ -static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE8A iface) -{ - SysMouseImpl *This = (SysMouseImpl *)iface; - ULONG ref; - - ref = InterlockedDecrement(&This->base.ref); - if (ref) - return ref; - - IDirectInputDevice_Unacquire(iface); - - /* Free the data queue */ - HeapFree(GetProcessHeap(), 0, This->base.data_queue); - - /* Free data format */ - HeapFree(GetProcessHeap(), 0, This->base.data_format.wine_df->rgodf); - HeapFree(GetProcessHeap(), 0, This->base.data_format.wine_df); - release_DataFormat(&This->base.data_format); - - IDirectInput_Release((LPDIRECTINPUTDEVICE8A)This->dinput); - This->base.crit.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->base.crit); - HeapFree(GetProcessHeap(),0,This); - return 0; -} - /* low-level mouse hook */ static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lparam ) { @@ -317,7 +286,7 @@ static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lpara if (pt.x) queue_event((LPDIRECTINPUTDEVICE8A)This, id_to_offset(&This->base.data_format, DIDFT_MAKEINSTANCE(WINE_MOUSE_X_AXIS_INSTANCE) | DIDFT_RELAXIS), - pt1.x, hook->time, This->dinput->evsequence); + pt1.x, hook->time, This->base.dinput->evsequence); if (pt.y) { inst_id = DIDFT_MAKEINSTANCE(WINE_MOUSE_Y_AXIS_INSTANCE) | DIDFT_RELAXIS; @@ -376,7 +345,7 @@ static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lpara } if (inst_id != -1) queue_event((LPDIRECTINPUTDEVICE8A)This, id_to_offset(&This->base.data_format, inst_id), - wdata, hook->time, This->dinput->evsequence++); + wdata, hook->time, This->base.dinput->evsequence++); LeaveCriticalSection(&This->base.crit); @@ -636,7 +605,7 @@ static HRESULT WINAPI SysMouseAImpl_GetCapabilities( devcaps.dwSize = lpDIDevCaps->dwSize; devcaps.dwFlags = DIDC_ATTACHED; - if (This->dinput->dwVersion >= 0x0800) + if (This->base.dinput->dwVersion >= 0x0800) devcaps.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8); else devcaps.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8); @@ -715,7 +684,7 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceInfo( return DI_OK; } - fill_mouse_dideviceinstanceA(pdidi, This->dinput->dwVersion); + fill_mouse_dideviceinstanceA(pdidi, This->base.dinput->dwVersion); return DI_OK; } @@ -730,7 +699,7 @@ static HRESULT WINAPI SysMouseWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, L return DI_OK; } - fill_mouse_dideviceinstanceW(pdidi, This->dinput->dwVersion); + fill_mouse_dideviceinstanceW(pdidi, This->base.dinput->dwVersion); return DI_OK; } @@ -740,7 +709,7 @@ static const IDirectInputDevice8AVtbl SysMouseAvt = { IDirectInputDevice2AImpl_QueryInterface, IDirectInputDevice2AImpl_AddRef, - SysMouseAImpl_Release, + IDirectInputDevice2AImpl_Release, SysMouseAImpl_GetCapabilities, IDirectInputDevice2AImpl_EnumObjects, SysMouseAImpl_GetProperty, @@ -782,7 +751,7 @@ static const IDirectInputDevice8WVtbl SysMouseWvt = { IDirectInputDevice2WImpl_QueryInterface, XCAST(AddRef)IDirectInputDevice2AImpl_AddRef, - XCAST(Release)SysMouseAImpl_Release, + XCAST(Release)IDirectInputDevice2AImpl_Release, XCAST(GetCapabilities)SysMouseAImpl_GetCapabilities, IDirectInputDevice2WImpl_EnumObjects, XCAST(GetProperty)SysMouseAImpl_GetProperty, diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index 39c097a0e4b..d8d7dc61395 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c @@ -64,8 +64,11 @@ static void DSOUND_RecalcPrimary(DirectSoundDevice *device) device->fraglen = fraglen; TRACE("fraglen=%d\n", device->fraglen); } + if (device->hwbuf && device->drvdesc.dwFlags & DSDDESC_DONTNEEDWRITELEAD) + device->writelead = 0; + else /* calculate the 10ms write lead */ - device->writelead = (device->pwfx->nSamplesPerSec / 100) * nBlockAlign; + device->writelead = (device->pwfx->nSamplesPerSec / 100) * nBlockAlign; } static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device) diff --git a/dlls/mshtml/conpoint.c b/dlls/mshtml/conpoint.c index 9077baf8361..b5c969c82cd 100644 --- a/dlls/mshtml/conpoint.c +++ b/dlls/mshtml/conpoint.c @@ -36,21 +36,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(mshtml); #define CONPOINT(x) ((IConnectionPoint*) &(x)->lpConnectionPointVtbl); -struct ConnectionPoint { - const IConnectionPointVtbl *lpConnectionPointVtbl; - - HTMLDocument *doc; - - union { - IUnknown *unk; - IDispatch *disp; - IPropertyNotifySink *propnotif; - } *sinks; - DWORD sinks_size; - - IID iid; -}; - void call_property_onchanged(ConnectionPoint *This, DISPID dispid) { DWORD i; @@ -90,13 +75,13 @@ static HRESULT WINAPI ConnectionPoint_QueryInterface(IConnectionPoint *iface, static ULONG WINAPI ConnectionPoint_AddRef(IConnectionPoint *iface) { ConnectionPoint *This = CONPOINT_THIS(iface); - return IHTMLDocument2_AddRef(HTMLDOC(This->doc)); + return IConnectionPointContainer_AddRef(This->container); } static ULONG WINAPI ConnectionPoint_Release(IConnectionPoint *iface) { ConnectionPoint *This = CONPOINT_THIS(iface); - return IHTMLDocument2_Release(HTMLDOC(This->doc)); + return IConnectionPointContainer_Release(This->container); } static HRESULT WINAPI ConnectionPoint_GetConnectionInterface(IConnectionPoint *iface, IID *pIID) @@ -122,7 +107,7 @@ static HRESULT WINAPI ConnectionPoint_GetConnectionPointContainer(IConnectionPoi if(!ppCPC) return E_POINTER; - *ppCPC = CONPTCONT(This->doc); + *ppCPC = This->container; IConnectionPointContainer_AddRef(*ppCPC); return S_OK; } @@ -199,17 +184,18 @@ static const IConnectionPointVtbl ConnectionPointVtbl = ConnectionPoint_EnumConnections }; -static void ConnectionPoint_Create(HTMLDocument *doc, REFIID riid, ConnectionPoint **cp) +void ConnectionPoint_Init(ConnectionPoint *cp, IConnectionPointContainer *container, + REFIID riid, ConnectionPoint *prev) { - ConnectionPoint *ret = mshtml_alloc(sizeof(ConnectionPoint)); - - ret->lpConnectionPointVtbl = &ConnectionPointVtbl; - ret->doc = doc; - ret->sinks = NULL; - ret->sinks_size = 0; - memcpy(&ret->iid, riid, sizeof(IID)); - - *cp = ret; + cp->lpConnectionPointVtbl = &ConnectionPointVtbl; + cp->container = container; + cp->sinks = NULL; + cp->sinks_size = 0; + cp->iid = *riid; + cp->next = NULL; + + if(prev) + prev->next = cp; } static void ConnectionPoint_Destroy(ConnectionPoint *This) @@ -222,34 +208,33 @@ static void ConnectionPoint_Destroy(ConnectionPoint *This) } mshtml_free(This->sinks); - mshtml_free(This); } -#define CONPTCONT_THIS(iface) DEFINE_THIS(HTMLDocument, ConnectionPointContainer, iface) +#define CONPTCONT_THIS(iface) DEFINE_THIS(ConnectionPointContainer, ConnectionPointContainer, iface) static HRESULT WINAPI ConnectionPointContainer_QueryInterface(IConnectionPointContainer *iface, REFIID riid, void **ppv) { - HTMLDocument *This = CONPTCONT_THIS(iface); - return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv); + ConnectionPointContainer *This = CONPTCONT_THIS(iface); + return IUnknown_QueryInterface(This->outer, riid, ppv); } static ULONG WINAPI ConnectionPointContainer_AddRef(IConnectionPointContainer *iface) { - HTMLDocument *This = CONPTCONT_THIS(iface); - return IHTMLDocument2_AddRef(HTMLDOC(This)); + ConnectionPointContainer *This = CONPTCONT_THIS(iface); + return IUnknown_AddRef(This->outer); } static ULONG WINAPI ConnectionPointContainer_Release(IConnectionPointContainer *iface) { - HTMLDocument *This = CONPTCONT_THIS(iface); - return IHTMLDocument2_Release(HTMLDOC(This)); + ConnectionPointContainer *This = CONPTCONT_THIS(iface); + return IUnknown_Release(This->outer); } static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionPointContainer *iface, IEnumConnectionPoints **ppEnum) { - HTMLDocument *This = CONPTCONT_THIS(iface); + ConnectionPointContainer *This = CONPTCONT_THIS(iface); FIXME("(%p)->(%p)\n", This, ppEnum); return E_NOTIMPL; } @@ -257,19 +242,16 @@ static HRESULT WINAPI ConnectionPointContainer_EnumConnectionPoints(IConnectionP static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPointContainer *iface, REFIID riid, IConnectionPoint **ppCP) { - HTMLDocument *This = CONPTCONT_THIS(iface); + ConnectionPointContainer *This = CONPTCONT_THIS(iface); + ConnectionPoint *iter; + + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppCP); *ppCP = NULL; - if(IsEqualGUID(&DIID_HTMLDocumentEvents, riid)) { - TRACE("(%p)->(DIID_HTMLDocumentEvents %p)\n", This, ppCP); - *ppCP = CONPOINT(This->cp_htmldocevents); - }else if(IsEqualGUID(&DIID_HTMLDocumentEvents2, riid)) { - TRACE("(%p)->(DIID_HTMLDocumentEvents2 %p)\n", This, ppCP); - *ppCP = CONPOINT(This->cp_htmldocevents2); - }else if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) { - TRACE("(%p)->(IID_IPropertyNotifySink %p)\n", This, ppCP); - *ppCP = CONPOINT(This->cp_propnotif); + for(iter = This->cp_list; iter; iter = iter->next) { + if(IsEqualGUID(&iter->iid, riid)) + *ppCP = CONPOINT(iter); } if(*ppCP) { @@ -277,7 +259,7 @@ static HRESULT WINAPI ConnectionPointContainer_FindConnectionPoint(IConnectionPo return S_OK; } - FIXME("(%p)->(%s %p) unsupported riid\n", This, debugstr_guid(riid), ppCP); + FIXME("unsupported riid %s\n", debugstr_guid(riid)); return CONNECT_E_NOCONNECTION; } @@ -291,18 +273,20 @@ static const IConnectionPointContainerVtbl ConnectionPointContainerVtbl = { #undef CONPTCONT_THIS -void HTMLDocument_ConnectionPoints_Init(HTMLDocument *This) +void ConnectionPointContainer_Init(ConnectionPointContainer *This, ConnectionPoint *cp_list, + IUnknown *outer) { This->lpConnectionPointContainerVtbl = &ConnectionPointContainerVtbl; - - ConnectionPoint_Create(This, &IID_IPropertyNotifySink, &This->cp_propnotif); - ConnectionPoint_Create(This, &DIID_HTMLDocumentEvents, &This->cp_htmldocevents); - ConnectionPoint_Create(This, &DIID_HTMLDocumentEvents2, &This->cp_htmldocevents2); + This->cp_list = cp_list; + This->outer = outer; } -void HTMLDocument_ConnectionPoints_Destroy(HTMLDocument *This) +void ConnectionPointContainer_Destroy(ConnectionPointContainer *This) { - ConnectionPoint_Destroy(This->cp_propnotif); - ConnectionPoint_Destroy(This->cp_htmldocevents); - ConnectionPoint_Destroy(This->cp_htmldocevents2); + ConnectionPoint *iter = This->cp_list; + + while(iter) { + ConnectionPoint_Destroy(iter); + iter = iter->next; + } } diff --git a/dlls/mshtml/htmlbody.c b/dlls/mshtml/htmlbody.c index ee23922ed4d..40d8983acc7 100644 --- a/dlls/mshtml/htmlbody.c +++ b/dlls/mshtml/htmlbody.c @@ -40,6 +40,10 @@ typedef struct { HTMLTextContainer text_container; + ConnectionPointContainer cp_container; + ConnectionPoint cp_propnotif; + ConnectionPoint cp_txtcontevents; + HTMLElement *element; nsIDOMHTMLBodyElement *nsbody; } HTMLBodyElement; @@ -68,6 +72,9 @@ static HRESULT WINAPI HTMLBodyElement_QueryInterface(IHTMLBodyElement *iface, }else if(IsEqualGUID(&IID_IHTMLTextContainer, riid)) { TRACE("(%p)->(IID_IHTMLTextContainer %p)\n", This, ppv); *ppv = HTMLTEXTCONT(&This->text_container); + }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) { + TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv); + *ppv = CONPTCONT(&This->cp_container); } if(*ppv) { @@ -428,6 +435,7 @@ static void HTMLBodyElement_destructor(IUnknown *iface) { HTMLBodyElement *This = HTMLBODY_THIS(iface); + ConnectionPointContainer_Destroy(&This->cp_container); nsIDOMHTMLBodyElement_Release(This->nsbody); mshtml_free(This); } @@ -487,6 +495,12 @@ void HTMLBodyElement_Create(HTMLElement *element) HTMLTextContainer_Init(&ret->text_container, element); + ConnectionPoint_Init(&ret->cp_propnotif, CONPTCONT(&ret->cp_container), + &IID_IPropertyNotifySink, NULL); + ConnectionPoint_Init(&ret->cp_txtcontevents, CONPTCONT(&ret->cp_container), + &DIID_HTMLTextContainerEvents, &ret->cp_propnotif); + ConnectionPointContainer_Init(&ret->cp_container, &ret->cp_propnotif, (IUnknown*)HTMLBODY(ret)); + nsres = nsIDOMHTMLElement_QueryInterface(element->nselem, &IID_nsIDOMHTMLBodyElement, (void**)&ret->nsbody); if(NS_FAILED(nsres)) diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index a606dace389..746c67af9fc 100644 --- a/dlls/mshtml/htmldoc.c +++ b/dlls/mshtml/htmldoc.c @@ -109,7 +109,7 @@ static HRESULT WINAPI HTMLDocument_QueryInterface(IHTMLDocument2 *iface, REFIID *ppvObject = HLNKTARGET(This); }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) { TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppvObject); - *ppvObject = CONPTCONT(This); + *ppvObject = CONPTCONT(&This->cp_container); }else if(IsEqualGUID(&IID_IPersistStreamInit, riid)) { TRACE("(%p)->(IID_IPersistStreamInit %p)\n", This, ppvObject); *ppvObject = PERSTRINIT(This); @@ -171,7 +171,7 @@ static ULONG WINAPI HTMLDocument_Release(IHTMLDocument2 *iface) release_nodes(This); - HTMLDocument_ConnectionPoints_Destroy(This); + ConnectionPointContainer_Destroy(&This->cp_container); if(This->nscontainer) NSContainer_Release(This->nscontainer); @@ -1141,7 +1141,14 @@ HRESULT HTMLDocument_Create(IUnknown *pUnkOuter, REFIID riid, void** ppvObject) HTMLDocument_Window_Init(ret); HTMLDocument_Service_Init(ret); HTMLDocument_Hlink_Init(ret); - HTMLDocument_ConnectionPoints_Init(ret); + + ConnectionPoint_Init(&ret->cp_propnotif, CONPTCONT(&ret->cp_container), + &IID_IPropertyNotifySink, NULL); + ConnectionPoint_Init(&ret->cp_htmldocevents, CONPTCONT(&ret->cp_container), + &DIID_HTMLDocumentEvents, &ret->cp_propnotif); + ConnectionPoint_Init(&ret->cp_htmldocevents2, CONPTCONT(&ret->cp_container), + &DIID_HTMLDocumentEvents2, &ret->cp_htmldocevents); + ConnectionPointContainer_Init(&ret->cp_container, &ret->cp_propnotif, (IUnknown*)HTMLDOC(ret)); ret->nscontainer = NSContainer_Create(ret, NULL); ret->window = HTMLWindow_Create(ret); diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 1b8b02f012e..244a0e468d1 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -71,6 +71,30 @@ typedef enum { EDITMODE } USERMODE; +typedef struct { + const IConnectionPointContainerVtbl *lpConnectionPointContainerVtbl; + + ConnectionPoint *cp_list; + IUnknown *outer; +} ConnectionPointContainer; + +struct ConnectionPoint { + const IConnectionPointVtbl *lpConnectionPointVtbl; + + IConnectionPointContainer *container; + + union { + IUnknown *unk; + IDispatch *disp; + IPropertyNotifySink *propnotif; + } *sinks; + DWORD sinks_size; + + IID iid; + + ConnectionPoint *next; +}; + struct HTMLDocument { const IHTMLDocument2Vtbl *lpHTMLDocument2Vtbl; const IHTMLDocument3Vtbl *lpHTMLDocument3Vtbl; @@ -87,7 +111,6 @@ struct HTMLDocument { const IOleCommandTargetVtbl *lpOleCommandTargetVtbl; const IOleControlVtbl *lpOleControlVtbl; const IHlinkTargetVtbl *lpHlinkTargetVtbl; - const IConnectionPointContainerVtbl *lpConnectionPointContainerVtbl; const IPersistStreamInitVtbl *lpPersistStreamInitVtbl; LONG ref; @@ -120,9 +143,10 @@ struct HTMLDocument { DWORD update; - ConnectionPoint *cp_htmldocevents; - ConnectionPoint *cp_htmldocevents2; - ConnectionPoint *cp_propnotif; + ConnectionPointContainer cp_container; + ConnectionPoint cp_htmldocevents; + ConnectionPoint cp_htmldocevents2; + ConnectionPoint cp_propnotif; HTMLDOMNode *nodes; }; @@ -321,9 +345,10 @@ void HTMLDocument_View_Init(HTMLDocument*); void HTMLDocument_Window_Init(HTMLDocument*); void HTMLDocument_Service_Init(HTMLDocument*); void HTMLDocument_Hlink_Init(HTMLDocument*); -void HTMLDocument_ConnectionPoints_Init(HTMLDocument*); -void HTMLDocument_ConnectionPoints_Destroy(HTMLDocument*); +void ConnectionPoint_Init(ConnectionPoint*,IConnectionPointContainer*,REFIID,ConnectionPoint*); +void ConnectionPointContainer_Init(ConnectionPointContainer*,ConnectionPoint*,IUnknown*); +void ConnectionPointContainer_Destroy(ConnectionPointContainer*); NSContainer *NSContainer_Create(HTMLDocument*,NSContainer*); void NSContainer_Release(NSContainer*); diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c index 58ca42229f0..3b606d6cc53 100644 --- a/dlls/mshtml/persist.c +++ b/dlls/mshtml/persist.c @@ -177,7 +177,7 @@ static HRESULT set_moniker(HTMLDocument *This, IMoniker *mon, IBindCtx *pibc, BO } This->readystate = READYSTATE_LOADING; - call_property_onchanged(This->cp_propnotif, DISPID_READYSTATE); + call_property_onchanged(&This->cp_propnotif, DISPID_READYSTATE); update_doc(This, UPDATE_TITLE); HTMLDocument_LockContainer(This, TRUE); diff --git a/dlls/mshtml/task.c b/dlls/mshtml/task.c index 540c969acf6..5204a893cae 100644 --- a/dlls/mshtml/task.c +++ b/dlls/mshtml/task.c @@ -135,10 +135,10 @@ static void set_parsecomplete(HTMLDocument *doc) if(doc->usermode == EDITMODE) init_editor(doc); - call_property_onchanged(doc->cp_propnotif, 1005); + call_property_onchanged(&doc->cp_propnotif, 1005); doc->readystate = READYSTATE_INTERACTIVE; - call_property_onchanged(doc->cp_propnotif, DISPID_READYSTATE); + call_property_onchanged(&doc->cp_propnotif, DISPID_READYSTATE); if(doc->client) IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd); @@ -163,7 +163,7 @@ static void set_parsecomplete(HTMLDocument *doc) } doc->readystate = READYSTATE_COMPLETE; - call_property_onchanged(doc->cp_propnotif, DISPID_READYSTATE); + call_property_onchanged(&doc->cp_propnotif, DISPID_READYSTATE); if(doc->frame) { static const WCHAR wszDone[] = {'D','o','n','e',0}; diff --git a/dlls/msi/action.c b/dlls/msi/action.c index b550e54d6e4..cc2583de619 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -2512,19 +2512,26 @@ static UINT ITERATE_LaunchConditions(MSIRECORD *row, LPVOID param) MSIPACKAGE* package = (MSIPACKAGE*)param; LPCWSTR cond = NULL; LPCWSTR message = NULL; + UINT r; + static const WCHAR title[]= {'I','n','s','t','a','l','l',' ','F','a', 'i','l','e','d',0}; cond = MSI_RecordGetString(row,1); - if (MSI_EvaluateConditionW(package,cond) != MSICONDITION_TRUE) + r = MSI_EvaluateConditionW(package,cond); + if (r == MSICONDITION_FALSE) { - LPWSTR deformated; - message = MSI_RecordGetString(row,2); - deformat_string(package,message,&deformated); - MessageBoxW(NULL,deformated,title,MB_OK); - msi_free(deformated); - return ERROR_FUNCTION_FAILED; + if ((gUILevel & INSTALLUILEVEL_MASK) != INSTALLUILEVEL_NONE) + { + LPWSTR deformated; + message = MSI_RecordGetString(row,2); + deformat_string(package,message,&deformated); + MessageBoxW(NULL,deformated,title,MB_OK); + msi_free(deformated); + } + + return ERROR_INSTALL_FAILURE; } return ERROR_SUCCESS; diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c index be1ff7e6b24..2844a2698c0 100644 --- a/dlls/msi/tests/package.c +++ b/dlls/msi/tests/package.c @@ -147,6 +147,15 @@ static UINT create_signature_table( MSIHANDLE hdb ) "PRIMARY KEY `Signature`)" ); } +static UINT create_launchcondition_table( MSIHANDLE hdb ) +{ + return run_query( hdb, + "CREATE TABLE `LaunchCondition` (" + "`Condition` CHAR(255) NOT NULL, " + "`Description` CHAR(255) NOT NULL " + "PRIMARY KEY `Condition`)" ); +} + static UINT add_component_entry( MSIHANDLE hdb, const char *values ) { char insert[] = "INSERT INTO `Component` " @@ -259,6 +268,22 @@ static UINT add_signature_entry( MSIHANDLE hdb, const char *values ) return r; } +static UINT add_launchcondition_entry( MSIHANDLE hdb, const char *values ) +{ + char insert[] = "INSERT INTO `LaunchCondition` " + "(`Condition`, `Description`) " + "VALUES( %s )"; + char *query; + UINT sz, r; + + sz = strlen(values) + sizeof insert; + query = HeapAlloc(GetProcessHeap(),0,sz); + sprintf(query,insert,values); + r = run_query( hdb, query ); + HeapFree(GetProcessHeap(), 0, query); + return r; +} + static UINT set_summary_info(MSIHANDLE hdb) { UINT res; @@ -1329,6 +1354,29 @@ static void test_condition(void) r = MsiEvaluateCondition(hpkg, "one < \"1\""); ok( r == MSICONDITION_FALSE, "wrong return val\n"); + MsiSetProperty(hpkg, "X", "5.0"); + + r = MsiEvaluateCondition(hpkg, "X != \"\""); + ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r); + + r = MsiEvaluateCondition(hpkg, "X =\"5.0\""); + ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r); + + r = MsiEvaluateCondition(hpkg, "X =\"5.1\""); + ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r); + + r = MsiEvaluateCondition(hpkg, "X =\"6.0\""); + ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r); + + r = MsiEvaluateCondition(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\""); + ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r); + + r = MsiEvaluateCondition(hpkg, "(X =\"5.0\" or X =\"5.1\" or X =\"6.0\")"); + ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r); + + r = MsiEvaluateCondition(hpkg, "X !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")"); + ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r); + MsiCloseHandle( hpkg ); DeleteFile(msifile); } @@ -3206,6 +3254,50 @@ static void test_prop_path(void) DeleteFile(msifile); } +static void test_launchconditions(void) +{ + MSIHANDLE hpkg; + MSIHANDLE hdb; + UINT r; + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + hdb = create_package_db(); + ok( hdb, "failed to create package database\n" ); + + r = create_launchcondition_table( hdb ); + ok( r == ERROR_SUCCESS, "cannot create LaunchCondition table: %d\n", r ); + + r = add_launchcondition_entry( hdb, "'X = \"1\"', 'one'" ); + ok( r == ERROR_SUCCESS, "cannot add launch condition: %d\n", r ); + + /* invalid condition */ + r = add_launchcondition_entry( hdb, "'X != \"1\"', 'one'" ); + ok( r == ERROR_SUCCESS, "cannot add launch condition: %d\n", r ); + + hpkg = package_from_db( hdb ); + ok( hpkg, "failed to create package\n"); + + MsiCloseHandle( hdb ); + + r = MsiSetProperty( hpkg, "X", "1" ); + ok( r == ERROR_SUCCESS, "failed to set property\n" ); + + /* invalid conditions are ignored */ + r = MsiDoAction( hpkg, "LaunchConditions" ); + ok( r == ERROR_SUCCESS, "cost init failed\n" ); + + /* verify LaunchConditions still does some verification */ + r = MsiSetProperty( hpkg, "X", "2" ); + ok( r == ERROR_SUCCESS, "failed to set property\n" ); + + r = MsiDoAction( hpkg, "LaunchConditions" ); + ok( r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r ); + + MsiCloseHandle( hpkg ); + DeleteFile( msifile ); +} + START_TEST(package) { test_createpackage(); @@ -3227,4 +3319,5 @@ START_TEST(package) test_installprops(); test_sourcedirprop(); test_prop_path(); + test_launchconditions(); } diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index 99754556118..d4ccf5f3817 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c @@ -2187,8 +2187,6 @@ static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS st NTSTATUS ret = STATUS_SUCCESS; int len, action, i; - TRACE("%p %p %08x\n", info, iosb, status); - SERVER_START_REQ( read_change ) { req->handle = info->FileHandle; @@ -2218,9 +2216,6 @@ static NTSTATUS read_changes_apc( void *user, PIO_STATUS_BLOCK iosb, NTSTATUS st pfni->Action = action; pfni->FileNameLength = len * sizeof (WCHAR); pfni->FileName[len] = 0; - - TRACE("action = %d name = %s\n", pfni->Action, - debugstr_w(pfni->FileName) ); len = sizeof (*pfni) - sizeof (DWORD) + pfni->FileNameLength; } else diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 2f23862dcea..e84490f358c 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -324,8 +324,6 @@ static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATU async_fileio_read *fileio = user; int fd, needs_close, result; - TRACE("%p %p 0x%x\n", iosb, fileio->buffer, status); - switch (status) { case STATUS_ALERTED: /* got some new data */ @@ -340,10 +338,7 @@ static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATU if (result < 0) { if (errno == EAGAIN || errno == EINTR) - { - TRACE("Deferred read %d\n", errno); status = STATUS_PENDING; - } else /* check to see if the transfer is complete */ status = FILE_GetNtStatus(); } @@ -364,10 +359,6 @@ static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATU */ status = (fileio->avail_mode) ? STATUS_SUCCESS : STATUS_PENDING; } - - TRACE("read %d more bytes %u/%u so far (%s)\n", - result, fileio->already, fileio->count, - (status == STATUS_SUCCESS) ? "success" : "pending"); } break; @@ -709,8 +700,6 @@ static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTAT int result, fd, needs_close; enum server_fd_type type; - TRACE("(%p %p 0x%x)\n",iosb, fileio->buffer, status); - switch (status) { case STATUS_ALERTED: @@ -735,7 +724,6 @@ static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTAT { fileio->already += result; status = (fileio->already < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS; - TRACE("wrote %d more bytes %u/%u so far\n", result, fileio->already, fileio->count); } break; diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index b1006080dd0..eaea02c4f94 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -131,7 +131,7 @@ static inline NTSTATUS init_teb( TEB *teb ) * * Make sure the unicode string doesn't point beyond the end pointer */ -static inline void fix_unicode_string( UNICODE_STRING *str, char *end_ptr ) +static inline void fix_unicode_string( UNICODE_STRING *str, const char *end_ptr ) { if ((char *)str->Buffer >= end_ptr) { diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 5964258c2df..7f42f59b8ba 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -366,9 +366,9 @@ static void add_reserved_area( void *addr, size_t size ) * * Check if an address range goes beyond a given limit. */ -static inline int is_beyond_limit( void *addr, size_t size, void *limit ) +static inline int is_beyond_limit( const void *addr, size_t size, const void *limit ) { - return (limit && (addr >= limit || (char *)addr + size > (char *)limit)); + return (limit && (addr >= limit || (const char *)addr + size > (const char *)limit)); } diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 832770ee1fd..11b08fe74c2 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -76,8 +76,9 @@ HINSTANCE OLE32_hInstance = 0; /* FIXME: make static ... */ * TODO: Most of these things will have to be made thread-safe. */ -static HRESULT COM_GetRegisteredClassObject(struct apartment *apt, REFCLSID rclsid, DWORD dwClsContext, LPUNKNOWN* ppUnk); -static void COM_RevokeAllClasses(struct apartment *apt); +static HRESULT COM_GetRegisteredClassObject(const struct apartment *apt, REFCLSID rclsid, + DWORD dwClsContext, LPUNKNOWN* ppUnk); +static void COM_RevokeAllClasses(const struct apartment *apt); static HRESULT get_inproc_class_object(APARTMENT *apt, HKEY hkeydll, REFCLSID rclsid, REFIID riid, void **ppv); static APARTMENT *MTA; /* protected by csApartment */ @@ -327,7 +328,7 @@ static APARTMENT *apartment_get_or_create(DWORD model) return apt; } -static inline BOOL apartment_is_model(APARTMENT *apt, DWORD model) +static inline BOOL apartment_is_model(const APARTMENT *apt, DWORD model) { return (apt->multi_threaded == !(model & COINIT_APARTMENTTHREADED)); } @@ -728,7 +729,7 @@ HRESULT apartment_createwindowifneeded(struct apartment *apt) return S_OK; } -HWND apartment_getwindow(struct apartment *apt) +HWND apartment_getwindow(const struct apartment *apt) { assert(!apt->multi_threaded); return apt->win; @@ -1754,11 +1755,8 @@ HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid) * to normal COM usage, this method will increase the * reference count on this object. */ -static HRESULT COM_GetRegisteredClassObject( - struct apartment *apt, - REFCLSID rclsid, - DWORD dwClsContext, - LPUNKNOWN* ppUnk) +static HRESULT COM_GetRegisteredClassObject(const struct apartment *apt, REFCLSID rclsid, + DWORD dwClsContext, LPUNKNOWN* ppUnk) { HRESULT hr = S_FALSE; RegisteredClass *curClass; @@ -1951,7 +1949,7 @@ static void COM_RevokeRegisteredClassObject(RegisteredClass *curClass) HeapFree(GetProcessHeap(), 0, curClass); } -static void COM_RevokeAllClasses(struct apartment *apt) +static void COM_RevokeAllClasses(const struct apartment *apt) { RegisteredClass *curClass, *cursor; diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index a5d83787d33..c12150af208 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -255,13 +255,13 @@ DWORD apartment_addref(struct apartment *apt); DWORD apartment_release(struct apartment *apt); HRESULT apartment_disconnectproxies(struct apartment *apt); void apartment_disconnectobject(struct apartment *apt, void *object); -static inline HRESULT apartment_getoxid(struct apartment *apt, OXID *oxid) +static inline HRESULT apartment_getoxid(const struct apartment *apt, OXID *oxid) { *oxid = apt->oxid; return S_OK; } HRESULT apartment_createwindowifneeded(struct apartment *apt); -HWND apartment_getwindow(struct apartment *apt); +HWND apartment_getwindow(const struct apartment *apt); void apartment_joinmta(void); diff --git a/dlls/pdh/pdh.spec b/dlls/pdh/pdh.spec index 3bea9492c75..42a66edfaf6 100644 --- a/dlls/pdh/pdh.spec +++ b/dlls/pdh/pdh.spec @@ -1,8 +1,8 @@ 1 stub PdhPlaGetLogFileNameA @ stub PdhAdd009CounterA @ stub PdhAdd009CounterW -@ stub PdhAddCounterA -@ stub PdhAddCounterW +@ stdcall PdhAddCounterA(ptr str long ptr) +@ stdcall PdhAddCounterW(ptr wstr long ptr) @ stub PdhBindInputDataSourceA @ stub PdhBindInputDataSourceW @ stub PdhBrowseCountersA @@ -11,8 +11,8 @@ @ stub PdhBrowseCountersW @ stub PdhCalculateCounterFromRawValue @ stub PdhCloseLog -@ stub PdhCloseQuery -@ stub PdhCollectQueryData +@ stdcall PdhCloseQuery(ptr) +@ stdcall PdhCollectQueryData(ptr) @ stub PdhCollectQueryDataEx @ stub PdhComputeCounterStatistics @ stub PdhConnectMachineA @@ -81,9 +81,9 @@ @ stub PdhOpenLogA @ stub PdhOpenLogW @ stub PdhOpenQuery -@ stub PdhOpenQueryA +@ stdcall PdhOpenQueryA(str long ptr) @ stub PdhOpenQueryH -@ stub PdhOpenQueryW +@ stdcall PdhOpenQueryW(wstr long ptr) @ stub PdhParseCounterPathA @ stub PdhParseCounterPathW @ stub PdhParseInstanceNameA @@ -120,7 +120,7 @@ @ stub PdhReadRawLogRecord @ stub PdhRelogA @ stub PdhRelogW -@ stub PdhRemoveCounter +@ stdcall PdhRemoveCounter(ptr) @ stub PdhSelectDataSourceA @ stub PdhSelectDataSourceW @ stub PdhSetCounterScaleFactor diff --git a/dlls/pdh/pdh_main.c b/dlls/pdh/pdh_main.c index cbc19916a43..b21391a807f 100644 --- a/dlls/pdh/pdh_main.c +++ b/dlls/pdh/pdh_main.c @@ -20,12 +20,56 @@ #include +#define NONAMELESSUNION +#define NONAMELESSSTRUCT #include "windef.h" #include "winbase.h" + +#include "pdh.h" +#include "pdhmsg.h" +#include "winperf.h" + #include "wine/debug.h" +#include "wine/list.h" +#include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(pdh); +static inline void *pdh_alloc( SIZE_T size ) +{ + return HeapAlloc( GetProcessHeap(), 0, size ); +} + +static inline void *pdh_alloc_zero( SIZE_T size ) +{ + return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size ); +} + +static inline void pdh_free( LPVOID mem ) +{ + HeapFree( GetProcessHeap(), 0, mem ); +} + +static inline WCHAR *pdh_strdup( const WCHAR *src ) +{ + WCHAR *dst; + + if (!src) return NULL; + if ((dst = pdh_alloc( (strlenW( src ) + 1) * sizeof(WCHAR) ))) strcpyW( dst, src ); + return dst; +} + +static inline WCHAR *pdh_strdup_aw( const char *src ) +{ + int len; + WCHAR *dst; + + if (!src) return NULL; + len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 ); + if ((dst = pdh_alloc( len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len ); + return dst; +} + BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { TRACE("(0x%p, %d, %p)\n",hinstDLL,fdwReason,lpvReserved); @@ -39,3 +83,252 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return TRUE; } + +struct counter +{ + struct list entry; + WCHAR *path; /* identifier */ + DWORD type; /* counter type */ + DWORD status; /* update status */ + LONG scale; /* scale factor */ + LONG defaultscale; /* default scale factor */ + DWORD_PTR user; /* user data */ + DWORD_PTR queryuser; /* query user data */ + LONGLONG base; /* samples per second */ + FILETIME stamp; /* time stamp */ + void (CALLBACK *collect)( struct counter * ); /* collect callback */ + union + { + LONG longvalue; + double doublevalue; + LONGLONG largevalue; + } one; /* first value */ + union + { + LONG longvalue; + double doublevalue; + LONGLONG largevalue; + } two; /* second value */ +}; + +static struct counter *create_counter( void ) +{ + struct counter *counter; + + if ((counter = pdh_alloc_zero( sizeof(struct counter) ))) return counter; + return NULL; +} + +#define PDH_MAGIC_QUERY 0x50444830 /* 'PDH0' */ + +struct query +{ + DWORD magic; /* signature */ + DWORD_PTR user; /* user data */ + struct list counters; /* counter list */ +}; + +static struct query *create_query( void ) +{ + struct query *query; + + if ((query = pdh_alloc_zero( sizeof(struct query) ))) + { + query->magic = PDH_MAGIC_QUERY; + list_init( &query->counters ); + return query; + } + return NULL; +} + +struct source +{ + const WCHAR *path; /* identifier */ + void (CALLBACK *collect)( struct counter * ); /* collect callback */ + DWORD type; /* counter type */ + LONG scale; /* default scale factor */ + LONGLONG base; /* samples per second */ +}; + +/* counter source registry */ +static const struct source counter_sources[] = +{ + { NULL, NULL, 0, 0, 0 } +}; + +/*********************************************************************** + * PdhAddCounterA (PDH.@) + */ +PDH_STATUS WINAPI PdhAddCounterA( PDH_HQUERY query, LPCSTR path, + DWORD_PTR userdata, PDH_HCOUNTER *counter ) +{ + PDH_STATUS ret; + WCHAR *pathW; + + TRACE("%p %s %lx %p\n", query, debugstr_a(path), userdata, counter); + + if (!path) return PDH_INVALID_ARGUMENT; + + if (!(pathW = pdh_strdup_aw( path ))) + return PDH_MEMORY_ALLOCATION_FAILURE; + + ret = PdhAddCounterW( query, pathW, userdata, counter ); + + pdh_free( pathW ); + return ret; +} + +/*********************************************************************** + * PdhAddCounterW (PDH.@) + */ +PDH_STATUS WINAPI PdhAddCounterW( PDH_HQUERY hquery, LPCWSTR path, + DWORD_PTR userdata, PDH_HCOUNTER *hcounter ) +{ + struct query *query = hquery; + struct counter *counter; + unsigned int i; + + TRACE("%p %s %lx %p\n", hquery, debugstr_w(path), userdata, hcounter); + + if (!path || !hcounter) return PDH_INVALID_ARGUMENT; + if (!query || (query->magic != PDH_MAGIC_QUERY)) return PDH_INVALID_HANDLE; + + *hcounter = NULL; + for (i = 0; i < sizeof(counter_sources) / sizeof(counter_sources[0]); i++) + { + if (strstrW( path, counter_sources[i].path )) + { + if ((counter = create_counter())) + { + counter->path = pdh_strdup( counter_sources[i].path ); + counter->collect = counter_sources[i].collect; + counter->type = counter_sources[i].type; + counter->defaultscale = counter_sources[i].scale; + counter->base = counter_sources[i].base; + counter->queryuser = query->user; + counter->user = userdata; + + list_add_tail( &query->counters, &counter->entry ); + + *hcounter = counter; + return ERROR_SUCCESS; + } + return PDH_MEMORY_ALLOCATION_FAILURE; + } + } + return PDH_CSTATUS_NO_COUNTER; +} + +/*********************************************************************** + * PdhCloseQuery (PDH.@) + */ +PDH_STATUS WINAPI PdhCloseQuery( PDH_HQUERY handle ) +{ + struct query *query = handle; + struct list *item; + + TRACE("%p\n", handle); + + if (!query || (query->magic != PDH_MAGIC_QUERY)) return PDH_INVALID_HANDLE; + + LIST_FOR_EACH( item, &query->counters ) + { + struct counter *counter = LIST_ENTRY( item, struct counter, entry ); + + list_remove( &counter->entry ); + + pdh_free( counter->path ); + pdh_free( counter ); + } + + pdh_free( query ); + return ERROR_SUCCESS; +} + +/*********************************************************************** + * PdhCollectQueryData (PDH.@) + */ +PDH_STATUS WINAPI PdhCollectQueryData( PDH_HQUERY handle ) +{ + struct query *query = handle; + struct list *item; + + TRACE("%p\n", handle); + + if (!query || (query->magic != PDH_MAGIC_QUERY)) return PDH_INVALID_HANDLE; + + LIST_FOR_EACH( item, &query->counters ) + { + SYSTEMTIME time; + struct counter *counter = LIST_ENTRY( item, struct counter, entry ); + + counter->collect( counter ); + + GetLocalTime( &time ); + SystemTimeToFileTime( &time, &counter->stamp ); + } + return ERROR_SUCCESS; +} + +/*********************************************************************** + * PdhOpenQueryA (PDH.@) + */ +PDH_STATUS WINAPI PdhOpenQueryA( LPCSTR source, DWORD_PTR userdata, PDH_HQUERY *query ) +{ + PDH_STATUS ret; + WCHAR *sourceW = NULL; + + TRACE("%s %lx %p\n", debugstr_a(source), userdata, query); + + if (source && !(sourceW = pdh_strdup_aw( source ))) return PDH_MEMORY_ALLOCATION_FAILURE; + + ret = PdhOpenQueryW( sourceW, userdata, query ); + pdh_free( sourceW ); + + return ret; +} + +/*********************************************************************** + * PdhOpenQueryW (PDH.@) + */ +PDH_STATUS WINAPI PdhOpenQueryW( LPCWSTR source, DWORD_PTR userdata, PDH_HQUERY *handle ) +{ + struct query *query; + + TRACE("%s %lx %p\n", debugstr_w(source), userdata, handle); + + if (!handle) return PDH_INVALID_ARGUMENT; + + if (source) + { + FIXME("log file data source not supported\n"); + return PDH_INVALID_ARGUMENT; + } + if ((query = create_query())) + { + query->user = userdata; + *handle = query; + + return ERROR_SUCCESS; + } + return PDH_MEMORY_ALLOCATION_FAILURE; +} + +/*********************************************************************** + * PdhRemoveCounter (PDH.@) + */ +PDH_STATUS WINAPI PdhRemoveCounter( PDH_HCOUNTER handle ) +{ + struct counter *counter = handle; + + TRACE("%p\n", handle); + + if (!counter) return PDH_INVALID_HANDLE; + + list_remove( &counter->entry ); + + pdh_free( counter->path ); + pdh_free( counter ); + + return ERROR_SUCCESS; +} diff --git a/dlls/riched20/Makefile.in b/dlls/riched20/Makefile.in index 87feccd0603..6b974e5b7a1 100644 --- a/dlls/riched20/Makefile.in +++ b/dlls/riched20/Makefile.in @@ -4,7 +4,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = riched20.dll IMPORTLIB = libriched20.$(IMPLIBEXT) -IMPORTS = ole32 user32 gdi32 kernel32 +IMPORTS = ole32 imm32 user32 gdi32 kernel32 EXTRALIBS = -luuid C_SRCS = \ diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c index b83fb415d1c..4cdb54a1be2 100644 --- a/dlls/riched20/editor.c +++ b/dlls/riched20/editor.c @@ -227,6 +227,7 @@ #define NO_SHLWAPI_STREAM #include "shlwapi.h" #include "rtf.h" +#include "imm.h" #define STACK_SIZE_DEFAULT 100 #define STACK_SIZE_MAX 1000 @@ -2515,6 +2516,64 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam, ME_RewrapRepaint(editor); return DefWindowProcW(hWnd, msg, wParam, lParam); } + /* IME messages to make richedit controls IME aware */ + case WM_IME_SETCONTEXT: + case WM_IME_CONTROL: + case WM_IME_SELECT: + case WM_IME_COMPOSITIONFULL: + return 0; + case WM_IME_STARTCOMPOSITION: + { + editor->imeStartIndex=ME_GetCursorOfs(editor,0); + ME_DeleteSelection(editor); + ME_CommitUndo(editor); + ME_UpdateRepaint(editor); + return 0; + } + case WM_IME_COMPOSITION: + { + HIMC hIMC; + + ME_Style *style = ME_GetInsertStyle(editor, 0); + hIMC = ImmGetContext(hWnd); + ME_DeleteSelection(editor); + ME_CommitUndo(editor); + ME_SaveTempStyle(editor); + if (lParam & GCS_RESULTSTR) + { + LPWSTR lpCompStr = NULL; + DWORD dwBufLen; + + dwBufLen = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0); + lpCompStr = HeapAlloc(GetProcessHeap(),0,dwBufLen + sizeof(WCHAR)); + ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, lpCompStr, dwBufLen); + lpCompStr[dwBufLen/sizeof(WCHAR)] = 0; + ME_InsertTextFromCursor(editor,0,lpCompStr,dwBufLen/sizeof(WCHAR),style); + } + else if (lParam & GCS_COMPSTR) + { + LPWSTR lpCompStr = NULL; + DWORD dwBufLen; + + dwBufLen = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0); + lpCompStr = HeapAlloc(GetProcessHeap(),0,dwBufLen + sizeof(WCHAR)); + ImmGetCompositionStringW(hIMC, GCS_COMPSTR, lpCompStr, dwBufLen); + lpCompStr[dwBufLen/sizeof(WCHAR)] = 0; + + ME_InsertTextFromCursor(editor,0,lpCompStr,dwBufLen/sizeof(WCHAR),style); + ME_SetSelection(editor,editor->imeStartIndex, + editor->imeStartIndex + dwBufLen/sizeof(WCHAR)); + } + ME_ReleaseStyle(style); + ME_UpdateRepaint(editor); + return 0; + } + case WM_IME_ENDCOMPOSITION: + { + ME_DeleteSelection(editor); + editor->imeStartIndex=-1; + return 0; + } case EM_GETOLEINTERFACE: { LPVOID *ppvObj = (LPVOID*) lParam; diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h index ee5dfe32944..7bb91d52445 100644 --- a/dlls/riched20/editstr.h +++ b/dlls/riched20/editstr.h @@ -322,6 +322,8 @@ typedef struct tagME_TextEditor BOOL AutoURLDetect_bEnable; WCHAR cPasswordMask; BOOL bHaveFocus; + /*for IME */ + int imeStartIndex; } ME_TextEditor; typedef struct tagME_Context diff --git a/dlls/shell32/shell32_Pt.rc b/dlls/shell32/shell32_Pt.rc index 0a6a274494a..0ae61a83d00 100644 --- a/dlls/shell32/shell32_Pt.rc +++ b/dlls/shell32/shell32_Pt.rc @@ -317,7 +317,7 @@ STRINGTABLE DISCARDABLE IDS_SHV_COLUMN11 "Grupo" /* special folders */ - IDS_DESKTOP "Área de trabalho" + IDS_DESKTOP "Ambiente de trabalho" IDS_MYCOMPUTER "O Meu Computador" /* context menus */ @@ -330,45 +330,45 @@ STRINGTABLE DISCARDABLE IDS_CREATEFOLDER_DENIED "Não pode criar nova pasta: Permissão negada." IDS_CREATEFOLDER_CAPTION "Erro durante a criação da nova pasta" - IDS_DELETEITEM_CAPTION "Confirmar exclusão de ficheiro" - IDS_DELETEFOLDER_CAPTION "Confirmar exclusão de pasta" - IDS_DELETEITEM_TEXT "VTem certeza que deseja excluir '%1'?" + IDS_DELETEITEM_CAPTION "Confirmar exclusão do ficheiro" + IDS_DELETEFOLDER_CAPTION "Confirmar exclusão da pasta" + IDS_DELETEITEM_TEXT "Tem a certeza que deseja excluir '%1'?" IDS_DELETEMULTIPLE_TEXT "Tem certeza que deseja excluir estes %1 itens?" IDS_OVERWRITEFILE_TEXT "Sobreescrever ficheiro %1?" - IDS_OVERWRITEFILE_CAPTION "Confirmar sobreescrever ficheiro" + IDS_OVERWRITEFILE_CAPTION "Confirmar sobreescrição do ficheiro" /* message box strings */ IDS_RESTART_TITLE "Reiniciar" IDS_RESTART_PROMPT "Deseja simular a reinicialização do Windows?" IDS_SHUTDOWN_TITLE "Desligar" - IDS_SHUTDOWN_PROMPT "Deseja finalizar a sessão no Wine?" + IDS_SHUTDOWN_PROMPT "Deseja finalizar esta sessão do Wine?" /* shell folder path default values */ IDS_PROGRAMS "Menu Iniciar\\Programas" IDS_PERSONAL "OS Meus Documentos" IDS_FAVORITES "Favoritos" IDS_STARTUP "Menu Iniciar\\Programas\\Iniciar" - IDS_RECENT "Recente" + IDS_RECENT "Recentes" IDS_SENDTO "Enviar Para" IDS_STARTMENU "Menu Iniciar" IDS_MYMUSIC "As Minhas Músicas" IDS_MYVIDEO "Os Meus Vídeos" - IDS_DESKTOPDIRECTORY "Ecrã" + IDS_DESKTOPDIRECTORY "Ambiente de Trabalho" IDS_NETHOOD "NetHood" IDS_TEMPLATES "Modelos" - IDS_APPDATA "Dados de aplicação" + IDS_APPDATA "Application Data" IDS_PRINTHOOD "PrintHood" - IDS_LOCAL_APPDATA "Configurações locais\\Dados de aplicativos" - IDS_INTERNET_CACHE "Configurações locais\\Temporary Internet Files" + IDS_LOCAL_APPDATA "Definições locais\\Application Data" + IDS_INTERNET_CACHE "Definições locais\\Temporary Internet Files" IDS_COOKIES "Cookies" - IDS_HISTORY "Configurações locais\\Histórico" - IDS_PROGRAM_FILES "Ficheiros de programas" + IDS_HISTORY "Definições locais\\Histórico" + IDS_PROGRAM_FILES "Programas" IDS_MYPICTURES "As Minhas Imagens" - IDS_PROGRAM_FILES_COMMON "Ficheiros de programas\\Ficheiros comuns" - IDS_COMMON_DOCUMENTS "Documentos" + IDS_PROGRAM_FILES_COMMON "Programas\\Ficheiros comuns" + IDS_COMMON_DOCUMENTS "Os Meus Documentos" IDS_ADMINTOOLS "Menu Iniciar\\Programas\\Ferramentas Administrativas" - IDS_COMMON_MUSIC "Documentos\\As Minhas Músicas" - IDS_COMMON_PICTURES "Documentos\\As Minhas Imagens" - IDS_COMMON_VIDEO "Documentos\\Os Meus Vídeos" - IDS_CDBURN_AREA "Configurações locais\\Dados de aplicativos\\Microsoft\\Gravação de CD" + IDS_COMMON_MUSIC "Os Meus Documentos\\As Minhas Músicas" + IDS_COMMON_PICTURES "Os Meus Documentos\\As Minhas Imagens" + IDS_COMMON_VIDEO "Os Meus Documentos\\Os Meus Vídeos" + IDS_CDBURN_AREA "Definições locais\\Application Data\\Microsoft\\CD Burning" } diff --git a/dlls/shell32/shelllink.c b/dlls/shell32/shelllink.c index aa21a4aa0f4..62fc3e5dfeb 100644 --- a/dlls/shell32/shelllink.c +++ b/dlls/shell32/shelllink.c @@ -399,7 +399,7 @@ static BOOL StartLinkProcessor( LPCOLESTR szLink ) { static const WCHAR szFormat[] = { 'w','i','n','e','m','e','n','u','b','u','i','l','d','e','r','.','e','x','e', - ' ','-','r',' ','"','%','s','"',0 }; + ' ','-','w',' ','"','%','s','"',0 }; LONG len; LPWSTR buffer; STARTUPINFOW si; @@ -417,11 +417,6 @@ static BOOL StartLinkProcessor( LPCOLESTR szLink ) memset(&si, 0, sizeof(si)); si.cb = sizeof(si); if (!CreateProcessW( NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) return FALSE; - - /* wait for a while to throttle the creation of linker processes */ - if( WAIT_OBJECT_0 != WaitForSingleObject( pi.hProcess, 10000 ) ) - WARN("Timed out waiting for shell linker\n"); - CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); @@ -1053,10 +1048,7 @@ static HRESULT WINAPI IPersistStream_fnSave( IStream* stm, BOOL fClearDirty) { - static const WCHAR wOpen[] = {'o','p','e','n',0}; - LINK_HEADER header; - WCHAR exePath[MAX_PATH]; ULONG count; DWORD zero; HRESULT r; @@ -1065,20 +1057,6 @@ static HRESULT WINAPI IPersistStream_fnSave( TRACE("%p %p %x\n", This, stm, fClearDirty); - *exePath = '\0'; - - if (This->sPath) - { - SHELL_FindExecutable(NULL, This->sPath, wOpen, exePath, MAX_PATH, - NULL, NULL, NULL, NULL); - /* - * windows can create lnk files to executables that do not exist yet - * so if the executable does not exist the just trust the path they - * gave us - */ - if (!*exePath) lstrcpyW(exePath,This->sPath); - } - memset(&header, 0, sizeof(header)); header.dwSize = sizeof(header); header.fStartup = This->iShowCmd; @@ -1130,7 +1108,7 @@ static HRESULT WINAPI IPersistStream_fnSave( } if( This->sPath ) - Stream_WriteLocationInfo( stm, exePath, &This->volume ); + Stream_WriteLocationInfo( stm, This->sPath, &This->volume ); if( This->sDescription ) r = Stream_WriteString( stm, This->sDescription ); diff --git a/dlls/shell32/tests/shelllink.c b/dlls/shell32/tests/shelllink.c index 473aae786b7..8db88bb1e74 100644 --- a/dlls/shell32/tests/shelllink.c +++ b/dlls/shell32/tests/shelllink.c @@ -158,9 +158,10 @@ static void test_get_set(void) ok(SUCCEEDED(r), "GetPath failed (0x%08x)\n", r); ok(*buffer=='\0', "GetPath returned '%s'\n", buffer); + /* Win98 returns S_FALSE, but WinXP returns S_OK */ str="c:\\nonexistent\\file"; r = IShellLinkA_SetPath(sl, str); - ok(r==S_FALSE, "SetPath failed (0x%08x)\n", r); + ok(r==S_FALSE || r==S_OK, "SetPath failed (0x%08x)\n", r); strcpy(buffer,"garbage"); r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); @@ -211,28 +212,28 @@ static void test_get_set(void) ok(lstrcmpi(buffer, mypath)==0, "GetPath returned '%s'\n", buffer); } - /* test path with quotes */ + /* test path with quotes (Win98 IShellLinkA_SetPath returns S_FALSE, WinXP returns S_OK) */ r = IShellLinkA_SetPath(sl, "\"c:\\nonexistent\\file\""); - ok(r==S_FALSE, "SetPath failed (0x%08x)\n", r); + ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r); r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); ok(r==S_OK, "GetPath failed (0x%08x)\n", r); ok(!lstrcmp(buffer, "C:\\nonexistent\\file"), "case doesn't match\n"); r = IShellLinkA_SetPath(sl, "\"c:\\foo"); - ok(r==S_FALSE, "SetPath failed (0x%08x)\n", r); + ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r); r = IShellLinkA_SetPath(sl, "\"\"c:\\foo"); - ok(r==S_FALSE, "SetPath failed (0x%08x)\n", r); + ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r); r = IShellLinkA_SetPath(sl, "c:\\foo\""); - ok(r==S_FALSE, "SetPath failed (0x%08x)\n", r); + ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r); r = IShellLinkA_SetPath(sl, "\"\"c:\\foo\""); - ok(r==S_FALSE, "SetPath failed (0x%08x)\n", r); + ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r); r = IShellLinkA_SetPath(sl, "\"\"c:\\foo\"\""); - ok(r==S_FALSE, "SetPath failed (0x%08x)\n", r); + ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r); /* Test Getting / Setting the arguments */ strcpy(buffer,"garbage"); @@ -306,7 +307,13 @@ static void test_get_set(void) */ #define lok ok_(__FILE__, line) -#define check_lnk(a,b) check_lnk_(__LINE__, (a), (b)) +#define lok_todo_4(todo_flag,a,b,c,d) \ + if ((todo & todo_flag) == 0) lok((a), (b), (c), (d)); \ + else todo_wine lok((a), (b), (c), (d)); +#define lok_todo_2(todo_flag,a,b) \ + if ((todo & todo_flag) == 0) lok((a), (b)); \ + else todo_wine lok((a), (b)); +#define check_lnk(a,b,c) check_lnk_(__LINE__, (a), (b), (c)) void create_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int save_fails) { @@ -382,7 +389,7 @@ void create_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int save_fails) IShellLinkA_Release(sl); } -static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc) +static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int todo) { HRESULT r; IShellLinkA *sl; @@ -417,7 +424,7 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc) strcpy(buffer,"garbage"); r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer)); lok(SUCCEEDED(r), "GetDescription failed (0x%08x)\n", r); - lok(lstrcmp(buffer, desc->description)==0, + lok_todo_4(0x1, lstrcmp(buffer, desc->description)==0, "GetDescription returned '%s' instead of '%s'\n", buffer, desc->description); } @@ -426,7 +433,7 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc) strcpy(buffer,"garbage"); r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer)); lok(SUCCEEDED(r), "GetWorkingDirectory failed (0x%08x)\n", r); - lok(lstrcmpi(buffer, desc->workdir)==0, + lok_todo_4(0x2, lstrcmpi(buffer, desc->workdir)==0, "GetWorkingDirectory returned '%s' instead of '%s'\n", buffer, desc->workdir); } @@ -435,7 +442,7 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc) strcpy(buffer,"garbage"); r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); lok(SUCCEEDED(r), "GetPath failed (0x%08x)\n", r); - lok(lstrcmpi(buffer, desc->path)==0, + lok_todo_4(0x4, lstrcmpi(buffer, desc->path)==0, "GetPath returned '%s' instead of '%s'\n", buffer, desc->path); } @@ -444,7 +451,7 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc) LPITEMIDLIST pidl=NULL; r = IShellLinkA_GetIDList(sl, &pidl); lok(SUCCEEDED(r), "GetIDList failed (0x%08x)\n", r); - lok(pILIsEqual(pidl, desc->pidl), + lok_todo_2(0x8, pILIsEqual(pidl, desc->pidl), "GetIDList returned an incorrect pidl\n"); } if (desc->showcmd) @@ -452,7 +459,7 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc) int i=0xdeadbeef; r = IShellLinkA_GetShowCmd(sl, &i); lok(SUCCEEDED(r), "GetShowCmd failed (0x%08x)\n", r); - lok(i==desc->showcmd, + lok_todo_4(0x10, i==desc->showcmd, "GetShowCmd returned 0x%0x instead of 0x%0x\n", i, desc->showcmd); } @@ -462,10 +469,10 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc) strcpy(buffer,"garbage"); r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); lok(SUCCEEDED(r), "GetIconLocation failed (0x%08x)\n", r); - lok(lstrcmpi(buffer, desc->icon)==0, + lok_todo_4(0x20, lstrcmpi(buffer, desc->icon)==0, "GetIconLocation returned '%s' instead of '%s'\n", buffer, desc->icon); - lok(i==desc->icon_id, + lok_todo_4(0x20, i==desc->icon_id, "GetIconLocation returned 0x%0x instead of 0x%0x\n", i, desc->icon_id); } @@ -474,7 +481,7 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc) WORD i=0xbeef; r = IShellLinkA_GetHotkey(sl, &i); lok(SUCCEEDED(r), "GetHotkey failed (0x%08x)\n", r); - lok(i==desc->hotkey, + lok_todo_4(0x40, i==desc->hotkey, "GetHotkey returned 0x%04x instead of 0x%04x\n", i, desc->hotkey); } @@ -489,6 +496,7 @@ static void test_load_save(void) char mydir[MAX_PATH]; char realpath[MAX_PATH]; char* p; + HANDLE hf; DWORD r; /* Save an empty .lnk file */ @@ -501,7 +509,7 @@ static void test_load_save(void) desc.path=""; desc.arguments=""; desc.icon=""; - check_lnk(lnkfile, &desc); + check_lnk(lnkfile, &desc, 0x0); /* Point a .lnk file to nonexistent files */ desc.description=""; @@ -514,7 +522,7 @@ static void test_load_save(void) desc.icon_id=1234; desc.hotkey=0; create_lnk(lnkfile, &desc, 0); - check_lnk(lnkfile, &desc); + check_lnk(lnkfile, &desc, 0x0); r=GetModuleFileName(NULL, mypath, sizeof(mypath)); ok(r>=0 && r=0 && r=0 && rlpVtbl->GetFlags( dl, &flags ); diff --git a/dlls/winealsa.drv/dsoutput.c b/dlls/winealsa.drv/dsoutput.c index e4c7d3fd1e6..e6958d338df 100644 --- a/dlls/winealsa.drv/dsoutput.c +++ b/dlls/winealsa.drv/dsoutput.c @@ -88,42 +88,46 @@ struct IDsDriverBufferImpl snd_pcm_t *pcm; snd_pcm_hw_params_t *hw_params; snd_pcm_sw_params_t *sw_params; - snd_pcm_uframes_t mmap_buflen_frames, mmap_pos, mmap_writeahead; + snd_pcm_uframes_t mmap_buflen_frames, mmap_pos, mmap_commitahead, mmap_writeahead; }; /** Fill buffers, for starting and stopping * Alsa won't start playing until everything is filled up * This also updates mmap_pos + * + * Returns: Amount of periods in use so snd_pcm_avail_update + * doesn't have to be called up to 4x in GetPosition() */ -static void CommitAll(IDsDriverBufferImpl *This) +static snd_pcm_uframes_t CommitAll(IDsDriverBufferImpl *This) { const snd_pcm_channel_area_t *areas; snd_pcm_uframes_t used; - const snd_pcm_uframes_t writeahead = This->mmap_writeahead; + const snd_pcm_uframes_t commitahead = This->mmap_commitahead; - TRACE("%p want to %ld\n", This, writeahead); used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm); - if (used < writeahead) + TRACE("%p needs to commit to %lu, used: %lu\n", This, commitahead, used); + if (used < commitahead) { - snd_pcm_uframes_t putin = writeahead - used; + snd_pcm_uframes_t done, putin = commitahead - used; snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin); - This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin); + done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin); + This->mmap_pos += done; + used += done; + putin = commitahead - used; - used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm); - if (This->mmap_pos == This->mmap_buflen_frames) + if (This->mmap_pos == This->mmap_buflen_frames && (snd_pcm_sframes_t)putin > 0) { - putin = writeahead; - used = This->mmap_buflen_frames - snd_pcm_avail_update(This->pcm); - putin -= used; - - if ((snd_pcm_sframes_t)putin > 0) - { - snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin); - This->mmap_pos += snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin); - } + snd_pcm_mmap_begin(This->pcm, &areas, &This->mmap_pos, &putin); + done = snd_pcm_mmap_commit(This->pcm, This->mmap_pos, putin); + This->mmap_pos += done; + used += done; } - } + + if (This->mmap_pos == This->mmap_buflen_frames) + This->mmap_pos = 0; + + return used; } static void CheckXRUN(IDsDriverBufferImpl* This) @@ -175,9 +179,11 @@ static int DSDB_CreateMMAP(IDsDriverBufferImpl* pdbi) mmap_mode = snd_pcm_type(pcm); if (mmap_mode == SND_PCM_TYPE_HW) - TRACE("mmap'd buffer is a hardware buffer.\n"); + TRACE("mmap'd buffer is a direct hardware buffer.\n"); + else if (mmap_mode == SND_PCM_TYPE_DMIX) + TRACE("mmap'd buffer is an ALSA dmix buffer\n"); else - TRACE("mmap'd buffer is an ALSA emulation of hardware buffer.\n"); + TRACE("mmap'd buffer is an ALSA type %d buffer\n", mmap_mode); err = snd_pcm_hw_params_get_period_size(hw_params, &psize, NULL); @@ -218,6 +224,7 @@ static int DSDB_CreateMMAP(IDsDriverBufferImpl* pdbi) ERR("Can't map sound device for direct access: %s\n", snd_strerror(err)); return DSERR_GENERIC; } + snd_pcm_format_set_silence(format, areas->addr, pdbi->mmap_buflen_frames); err = snd_pcm_mmap_commit(pcm, ofs, avail); pdbi->mmap_buffer = areas->addr; @@ -375,16 +382,23 @@ static HRESULT SetFormat(IDsDriverBufferImpl *This, LPWAVEFORMATEX pwfx, BOOL fo err = snd_pcm_hw_params_get_period_size(hw_params, &psize, NULL); TRACE("Period size is: %lu\n", psize); - if (psize > 512) + /* If period size is 'high', try to commit less + * dmix needs at least 2 buffers to work succesfully but prefers 3 + * however it seems to work ok if I just commit 2 1/2 buffers + */ + if (psize >= 512) { - if (++warnonce == 1) + if (psize > 512 && ++warnonce == 1) FIXME("Your alsa dmix period size is excessively high, unfortunately this is alsa default, try decreasing it to 512 or 256 (but double the amount of periods) if possible\n"); - This->mmap_writeahead = 3 * psize; + This->mmap_commitahead = 2 * psize + psize/2; + This->mmap_writeahead = 2 * psize; } - else + else { - This->mmap_writeahead = 3 * psize; - while (This->mmap_writeahead <= 512) This->mmap_writeahead += psize; + This->mmap_commitahead = 3 * psize; + while (This->mmap_commitahead <= 512) + This->mmap_commitahead += psize; + This->mmap_writeahead = This->mmap_commitahead; } if (This->pcm) @@ -405,6 +419,11 @@ static HRESULT SetFormat(IDsDriverBufferImpl *This, LPWAVEFORMATEX pwfx, BOOL fo if (err < 0) WARN("Failed to apply changes: %s\n", snd_strerror(err)); + if (!This->pcm) + This->pcm = pcm; + else + snd_pcm_close(pcm); + if (This->pcm) snd_pcm_hw_params_current(This->pcm, This->hw_params); @@ -468,21 +487,24 @@ static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface, } state = snd_pcm_state(This->pcm); - if (state == SND_PCM_STATE_RUNNING) + + if (state != SND_PCM_STATE_RUNNING) + CheckXRUN(This); + else { - snd_pcm_uframes_t avail; - avail = snd_pcm_avail_update(This->pcm); - hw_pptr = This->mmap_pos + avail; - hw_pptr %= This->mmap_buflen_frames; - hw_wptr = hw_pptr + This->mmap_writeahead - 512; + snd_pcm_uframes_t used = CommitAll(This); + + if (This->mmap_pos > used) + hw_pptr = This->mmap_pos - used; + else + hw_pptr = This->mmap_buflen_frames - used + This->mmap_pos; + + hw_wptr = hw_pptr + (This->mmap_writeahead > used ? used : This->mmap_writeahead); hw_wptr %= This->mmap_buflen_frames; - WARN("At position: %ld (%ld) - Avail %ld\n", hw_pptr, This->mmap_pos, avail); - assert((snd_pcm_sframes_t)hw_pptr >= 0); - } - else WARN("%p: State = %d\n", lpdwPlay, state); + hw_pptr %= This->mmap_buflen_frames; - CheckXRUN(This); - CommitAll(This); + TRACE("At position: %ld (%ld) - Used %ld\n", hw_pptr, This->mmap_pos, used); + } LeaveCriticalSection(&This->pcm_crst); @@ -575,7 +597,7 @@ static HRESULT WINAPI IDsDriverImpl_GetDriverDesc(PIDSDRIVER iface, PDSDRIVERDES IDsDriverImpl *This = (IDsDriverImpl *)iface; TRACE("(%p,%p)\n",iface,pDesc); memcpy(pDesc, &(WOutDev[This->wDevID].ds_desc), sizeof(DSDRIVERDESC)); - pDesc->dwFlags = DSDDESC_DONTNEEDPRIMARYLOCK | DSDDESC_DONTNEEDSECONDARYLOCK; + pDesc->dwFlags = DSDDESC_DONTNEEDPRIMARYLOCK | DSDDESC_DONTNEEDSECONDARYLOCK | DSDDESC_DONTNEEDWRITELEAD; pDesc->dnDevNode = WOutDev[This->wDevID].waveDesc.dnDevNode; pDesc->wVxdId = 0; pDesc->wReserved = 0; @@ -738,16 +760,15 @@ DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv) TRACE("driver created\n"); /* the HAL isn't much better than the HEL if we can't do mmap() */ - if (!(WOutDev[wDevID].outcaps.dwSupport & WAVECAPS_DIRECTSOUND)) { - ERR("DirectSound flag not set\n"); - MESSAGE("This sound card's driver does not support direct access\n"); - MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n"); - return MMSYSERR_NOTSUPPORTED; + if (!(WOutDev[wDevID].outcaps.dwSupport & WAVECAPS_DIRECTSOUND)) + { + WARN("MMAP not supported for this device, falling back to waveout, should be harmless\n"); + return MMSYSERR_NOTSUPPORTED; } *idrv = HeapAlloc(GetProcessHeap(),0,sizeof(IDsDriverImpl)); if (!*idrv) - return MMSYSERR_NOMEM; + return MMSYSERR_NOMEM; (*idrv)->lpVtbl = &dsdvt; (*idrv)->ref = 1; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index e750cc22adc..9556d65026d 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1819,7 +1819,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPR This->rev_tex_unit_map[state] = -1; } } - This->oneToOneTexUnitMap = TRUE; /* Setup the implicit swapchain */ TRACE("Creating implicit swapchain\n"); @@ -3222,7 +3221,38 @@ static void device_update_fixed_function_usage_map(IWineD3DDeviceImpl *This) { int i; for (i = 0; i < MAX_TEXTURES; ++i) { - This->fixed_function_usage_map[i] = This->stateBlock->textures[i] ? TRUE : FALSE; + WINED3DTEXTUREOP color_op = This->stateBlock->textureState[i][WINED3DTSS_COLOROP]; + WINED3DTEXTUREOP alpha_op = This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP]; + DWORD color_arg1 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG1] & WINED3DTA_SELECTMASK; + DWORD color_arg2 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG2] & WINED3DTA_SELECTMASK; + DWORD color_arg3 = This->stateBlock->textureState[i][WINED3DTSS_COLORARG0] & WINED3DTA_SELECTMASK; + DWORD alpha_arg1 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1] & WINED3DTA_SELECTMASK; + DWORD alpha_arg2 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2] & WINED3DTA_SELECTMASK; + DWORD alpha_arg3 = This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0] & WINED3DTA_SELECTMASK; + + if (color_op == WINED3DTOP_DISABLE) { + /* Not used, and disable higher stages */ + while (i < MAX_TEXTURES) { + This->fixed_function_usage_map[i] = FALSE; + ++i; + } + break; + } + + if (((color_arg1 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG2) + || ((color_arg2 == WINED3DTA_TEXTURE) && color_op != WINED3DTOP_SELECTARG1) + || ((color_arg3 == WINED3DTA_TEXTURE) && (color_op == WINED3DTOP_MULTIPLYADD || color_op == WINED3DTOP_LERP)) + || ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG2) + || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3DTOP_SELECTARG1) + || ((alpha_arg3 == WINED3DTA_TEXTURE) && (alpha_op == WINED3DTOP_MULTIPLYADD || alpha_op == WINED3DTOP_LERP))) { + This->fixed_function_usage_map[i] = TRUE; + } else { + This->fixed_function_usage_map[i] = FALSE; + } + + if ((color_op == WINED3DTOP_BUMPENVMAP || color_op == WINED3DTOP_BUMPENVMAPLUMINANCE) && i < MAX_TEXTURES - 1) { + This->fixed_function_usage_map[i+1] = TRUE; + } } } @@ -3232,47 +3262,23 @@ static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) { device_update_fixed_function_usage_map(This); if (This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) { - for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) { + for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) { + if (!This->fixed_function_usage_map[i]) continue; + if (This->texUnitMap[i] != i) { device_map_stage(This, i, i); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i)); - if (i < MAX_TEXTURES) { - markTextureStagesDirty(This, i); - } + markTextureStagesDirty(This, i); } } return; } - /* No pixel shader, and we do not have enough texture units available. Try to skip NULL textures - * First, see if we can succeed at all - */ - tex = 0; - for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) { - if (!This->fixed_function_usage_map[i]) ++tex; - } - - if (GL_LIMITS(textures) + tex < This->stateBlock->lowest_disabled_stage) { - FIXME("Too many bound textures to support the combiner settings\n"); - return; - } - /* Now work out the mapping */ tex = 0; - This->oneToOneTexUnitMap = FALSE; - WARN("Non 1:1 mapping UNTESTED!\n"); for (i = 0; i < This->stateBlock->lowest_disabled_stage; ++i) { - /* Skip NULL textures */ - if (!This->fixed_function_usage_map[i]) { - /* Map to -1, so the check below doesn't fail if a non-NULL - * texture is set on this stage */ - TRACE("Mapping texture stage %d to -1\n", i); - device_map_stage(This, i, -1); - - continue; - } + if (!This->fixed_function_usage_map[i]) continue; - TRACE("Mapping texture stage %d to unit %d\n", i, tex); if (This->texUnitMap[i] != tex) { device_map_stage(This, i, tex); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i)); @@ -3284,10 +3290,11 @@ static void device_map_fixed_function_samplers(IWineD3DDeviceImpl *This) { } static void device_map_psamplers(IWineD3DDeviceImpl *This) { + DWORD *sampler_tokens = ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.reg_maps.samplers; int i; for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) { - if (This->texUnitMap[i] != i) { + if (sampler_tokens[i] && This->texUnitMap[i] != i) { device_map_stage(This, i, i); IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i)); if (i < MAX_TEXTURES) { @@ -3297,7 +3304,69 @@ static void device_map_psamplers(IWineD3DDeviceImpl *This) { } } +static BOOL device_unit_free_for_vs(IWineD3DDeviceImpl *This, DWORD *pshader_sampler_tokens, DWORD *vshader_sampler_tokens, int unit) { + int current_mapping = This->rev_tex_unit_map[unit]; + + if (current_mapping == -1) { + /* Not currently used */ + return TRUE; + } + + if (current_mapping < MAX_FRAGMENT_SAMPLERS) { + /* Used by a fragment sampler */ + + if (!pshader_sampler_tokens) { + /* No pixel shader, check fixed function */ + return current_mapping >= MAX_TEXTURES || !This->fixed_function_usage_map[current_mapping]; + } + + /* Pixel shader, check the shader's sampler map */ + return !pshader_sampler_tokens[current_mapping]; + } + + /* Used by a vertex sampler */ + return !vshader_sampler_tokens[current_mapping]; +} + +static void device_map_vsamplers(IWineD3DDeviceImpl *This, BOOL ps) { + DWORD *vshader_sampler_tokens = ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.reg_maps.samplers; + DWORD *pshader_sampler_tokens = NULL; + int start = GL_LIMITS(combined_samplers) - 1; + int i; + + if (ps) { + IWineD3DPixelShaderImpl *pshader = (IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader; + + /* Make sure the shader's reg_maps are up to date. This is only relevant for 1.x pixelshaders. */ + IWineD3DPixelShader_CompileShader((IWineD3DPixelShader *)pshader); + pshader_sampler_tokens = pshader->baseShader.reg_maps.samplers; + } + + for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) { + int vsampler_idx = i + MAX_FRAGMENT_SAMPLERS; + if (vshader_sampler_tokens[i]) { + if (This->texUnitMap[vsampler_idx] != -1) { + /* Already mapped somewhere */ + continue; + } + + while (start >= 0) { + if (device_unit_free_for_vs(This, pshader_sampler_tokens, vshader_sampler_tokens, start)) { + device_map_stage(This, vsampler_idx, start); + IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(vsampler_idx)); + + --start; + break; + } + + --start; + } + } + } +} + void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) { + BOOL vs = use_vs(This); BOOL ps = use_ps(This); /* This code can assume that GL_NV_register_combiners are supported, otherwise * it is never called. @@ -3313,6 +3382,10 @@ void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) { } else { device_map_fixed_function_samplers(This); } + + if (vs) { + device_map_vsamplers(This, ps); + } } static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) { diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 11ede057ffe..1e77b96dc72 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -99,6 +99,29 @@ static void shader_glsl_load_psamplers( } } +static void shader_glsl_load_vsamplers(WineD3D_GL_Info *gl_info, IWineD3DStateBlock* iface) { + IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface; + GLhandleARB programId = stateBlock->glsl_program->programId; + GLhandleARB name_loc; + char sampler_name[20]; + int i; + + for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) { + snprintf(sampler_name, sizeof(sampler_name), "Vsampler%d", i); + name_loc = GL_EXTCALL(glGetUniformLocationARB(programId, sampler_name)); + if (name_loc != -1) { + int mapped_unit = stateBlock->wineD3DDevice->texUnitMap[MAX_FRAGMENT_SAMPLERS + i]; + if (mapped_unit != -1 && mapped_unit < GL_LIMITS(combined_samplers)) { + TRACE("Loading %s for texture %d\n", sampler_name, mapped_unit); + GL_EXTCALL(glUniform1iARB(name_loc, mapped_unit)); + checkGLcall("glUniform1iARB"); + } else { + ERR("Trying to load sampler %s on unsupported unit %d\n", sampler_name, mapped_unit); + } + } + } +} + /** * Loads floating point constants (aka uniforms) into the currently set GLSL program. * When constant_list == NULL, it will load all the constants. @@ -308,6 +331,9 @@ void shader_glsl_load_constants( constant_locations = stateBlock->glsl_program->vuniformF_locations; constant_list = &stateBlock->set_vconstantsF; + /* Load vertex shader samplers */ + shader_glsl_load_vsamplers(gl_info, (IWineD3DStateBlock*)stateBlock); + /* Load DirectX 9 float constants/uniforms for vertex shader */ shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF), stateBlock->vertexShaderConstantF, constant_locations, constant_list); @@ -1563,6 +1589,36 @@ void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) { } } +void shader_glsl_texldl(SHADER_OPCODE_ARG* arg) { + IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*)arg->shader; + glsl_sample_function_t sample_function; + glsl_src_param_t coord_param, lod_param; + char dst_swizzle[6]; + DWORD sampler_type; + DWORD sampler_idx; + + shader_glsl_append_dst(arg->buffer, arg); + shader_glsl_get_swizzle(arg->src[1], FALSE, arg->dst, dst_swizzle); + + sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK; + sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK; + shader_glsl_get_sample_function(sampler_type, FALSE, &sample_function); + shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], sample_function.coord_mask, &coord_param); + + shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_3, &lod_param); + + if (shader_is_pshader_version(This->baseShader.hex_version)) { + /* The GLSL spec claims the Lod sampling functions are only supported in vertex shaders. + * However, they seem to work just fine in fragment shaders as well. */ + WARN("Using %sLod in fragment shader.\n", sample_function.name); + shader_addline(arg->buffer, "%sLod(Psampler%u, %s, %s)%s);\n", + sample_function.name, sampler_idx, coord_param.param_str, lod_param.param_str, dst_swizzle); + } else { + shader_addline(arg->buffer, "%sLod(Vsampler%u, %s, %s)%s);\n", + sample_function.name, sampler_idx, coord_param.param_str, lod_param.param_str, dst_swizzle); + } +} + void pshader_glsl_texcoord(SHADER_OPCODE_ARG* arg) { /* FIXME: Make this work for more than just 2D textures */ diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 1f81fbdcf64..eb41d1f9792 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -256,7 +256,7 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = { {WINED3DSIO_DSY, "dsy", GLNAME_REQUIRE_GLSL, 1, 2, NULL, NULL, 0, 0}, {WINED3DSIO_TEXLDD, "texldd", GLNAME_REQUIRE_GLSL, 1, 5, NULL, NULL, WINED3DPS_VERSION(2,1), -1}, {WINED3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 1, 3, NULL, NULL, 0, 0}, - {WINED3DSIO_TEXLDL, "texldl", GLNAME_REQUIRE_GLSL, 1, 3, NULL, NULL, 0, 0}, + {WINED3DSIO_TEXLDL, "texldl", NULL, 1, 3, NULL, shader_glsl_texldl, WINED3DPS_VERSION(3,0), -1}, {WINED3DSIO_PHASE, "phase", GLNAME_REQUIRE_GLSL, 0, 0, NULL, NULL, 0, 0}, {0, NULL, NULL, 0, 0, NULL, NULL, 0, 0} }; diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index af6bc36bb97..cb3b8733aa5 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -156,7 +156,7 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = { {WINED3DSIO_LABEL, "label", NULL, 0, 1, NULL, shader_glsl_label, WINED3DVS_VERSION(2,0), -1}, {WINED3DSIO_SETP, "setp", GLNAME_REQUIRE_GLSL, 1, 3, NULL, NULL, 0, 0}, - {WINED3DSIO_TEXLDL, "texdl", GLNAME_REQUIRE_GLSL, 1, 3, NULL, NULL, 0, 0}, + {WINED3DSIO_TEXLDL, "texldl", NULL, 1, 3, NULL, shader_glsl_texldl, WINED3DVS_VERSION(3,0), -1}, {0, NULL, NULL, 0, 0, NULL, NULL, 0, 0} }; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index dd9a67db2e7..77978a37b72 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -727,7 +727,6 @@ struct IWineD3DDeviceImpl DWORD texUnitMap[MAX_COMBINED_SAMPLERS]; DWORD rev_tex_unit_map[MAX_COMBINED_SAMPLERS]; BOOL fixed_function_usage_map[MAX_TEXTURES]; - BOOL oneToOneTexUnitMap; /* Stream source management */ WineDirect3DVertexStridedData strided_streams; @@ -1737,6 +1736,7 @@ extern void shader_glsl_call(SHADER_OPCODE_ARG* arg); extern void shader_glsl_callnz(SHADER_OPCODE_ARG* arg); extern void shader_glsl_label(SHADER_OPCODE_ARG* arg); extern void shader_glsl_pow(SHADER_OPCODE_ARG* arg); +extern void shader_glsl_texldl(SHADER_OPCODE_ARG* arg); /** GLSL Pixel Shader Prototypes */ extern void pshader_glsl_tex(SHADER_OPCODE_ARG* arg); diff --git a/dlls/winemp3.acm/mpegl3.c b/dlls/winemp3.acm/mpegl3.c index 6d95a0bbcee..e960dbe4a2e 100644 --- a/dlls/winemp3.acm/mpegl3.c +++ b/dlls/winemp3.acm/mpegl3.c @@ -77,12 +77,14 @@ static const Format PCM_Formats[] = {1, 8, 11025}, {2, 8, 11025}, {1, 16, 11025}, {2, 16, 11025}, {1, 8, 22050}, {2, 8, 22050}, {1, 16, 22050}, {2, 16, 22050}, {1, 8, 44100}, {2, 8, 44100}, {1, 16, 44100}, {2, 16, 44100}, + {1, 8, 48000}, {2, 8, 48000}, {1, 16, 48000}, {2, 16, 48000}, }; static const Format MPEG3_Formats[] = { {1, 0, 8000}, {2, 0, 8000}, {1, 0, 11025}, {2, 0, 11025}, {1, 0, 22050}, {2, 0, 22050}, {1, 0, 44100}, {2, 0, 44100}, + {1, 0, 48000}, {2, 0, 48000}, }; #define NUM_PCM_FORMATS (sizeof(PCM_Formats) / sizeof(PCM_Formats[0])) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index aab38884206..90fa9b06873 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1074,8 +1074,6 @@ static int WS2_recv( int fd, struct iovec* iov, int count, struct msghdr hdr; union generic_unix_sockaddr unix_sockaddr; int n; - TRACE( "fd %d, iovec %p, count %d addr %s, len %p, flags %x\n", - fd, iov, count, debugstr_sockaddr(lpFrom), lpFromlen, *lpFlags); hdr.msg_name = NULL; @@ -1099,10 +1097,7 @@ static int WS2_recv( int fd, struct iovec* iov, int count, #endif if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 ) - { - TRACE( "recvmsg error %d\n", errno); return -1; - } if ( lpFrom && ws_sockaddr_u2ws( &unix_sockaddr.addr, lpFrom, lpFromlen ) != 0 ) @@ -1110,10 +1105,8 @@ static int WS2_recv( int fd, struct iovec* iov, int count, /* The from buffer was too small, but we read the data * anyway. Is that really bad? */ - WARN( "Address buffer too small\n" ); } - TRACE("-> %d\n", n); return n; } @@ -1127,8 +1120,6 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat ws2_async* wsa = user; int result = 0, fd; - TRACE( "(%p %p %x)\n", wsa, iosb, status ); - switch (status) { case STATUS_ALERTED: @@ -1141,7 +1132,6 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat if (result >= 0) { status = STATUS_SUCCESS; - TRACE( "received %d bytes\n", result ); _enable_event( wsa->hSocket, FD_READ, 0, 0 ); } else @@ -1150,13 +1140,11 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat { status = STATUS_PENDING; _enable_event( wsa->hSocket, FD_READ, 0, 0 ); - TRACE( "still pending\n" ); } else { result = 0; status = wsaErrno(); /* FIXME: is this correct ???? */ - TRACE( "Error: %x\n", status ); } } break; @@ -1180,10 +1168,9 @@ static int WS2_send( int fd, struct iovec* iov, int count, struct msghdr hdr; union generic_unix_sockaddr unix_addr; - TRACE( "fd %d, iovec %p, count %d, addr %s, len %d, flags %x\n", - fd, iov, count, debugstr_sockaddr(to), tolen, dwFlags); hdr.msg_name = NULL; + hdr.msg_namelen = 0; if ( to ) { @@ -1195,10 +1182,9 @@ static int WS2_send( int fd, struct iovec* iov, int count, return -1; } -#ifdef HAVE_IPX +#if defined(HAVE_IPX) && defined(SOL_IPX) if(to->sa_family == WS_AF_IPX) { -#ifdef SOL_IPX struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name; int val=0; unsigned int len=sizeof(int); @@ -1209,17 +1195,10 @@ static int WS2_send( int fd, struct iovec* iov, int count, * ipx type in the sockaddr_opx structure with the stored value. */ if(getsockopt(fd, SOL_IPX, IPX_TYPE, &val, &len) != -1) - { - TRACE("ptype: %d (fd:%d)\n", val, fd); uipx->sipx_type = val; - } -#endif } #endif - } - else - hdr.msg_namelen = 0; hdr.msg_iov = iov; hdr.msg_iovlen = count; @@ -1245,8 +1224,6 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu ws2_async* wsa = user; int result = 0, fd; - TRACE( "(%p %p %x)\n", wsa, iosb, status ); - switch (status) { case STATUS_ALERTED: @@ -1260,7 +1237,6 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu if (result >= 0) { status = STATUS_SUCCESS; - TRACE( "sent %d bytes\n", result ); _enable_event( wsa->hSocket, FD_WRITE, 0, 0 ); } else @@ -1269,7 +1245,6 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu { status = STATUS_PENDING; _enable_event( wsa->hSocket, FD_WRITE, 0, 0 ); - TRACE( "still pending\n" ); } else { @@ -1277,7 +1252,6 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu later in NtStatusToWSAError () */ status = wsaErrno(); result = 0; - TRACE( "Error: %x\n", status ); } } break; @@ -1300,7 +1274,6 @@ static NTSTATUS WS2_async_shutdown( void* user, PIO_STATUS_BLOCK iosb, NTSTATUS ws2_async* wsa = user; int fd, err = 1; - TRACE( "async %p %d\n", wsa, wsa->type ); switch (status) { case STATUS_ALERTED: @@ -4456,7 +4429,6 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString, LPINT lpAddressLength) { INT res=0; - struct in_addr inetaddr; LPSTR workBuffer=NULL,ptrPort; TRACE( "(%s, %x, %p, %p, %p)\n", AddressString, AddressFamily, lpProtocolInfo, @@ -4464,63 +4436,84 @@ INT WINAPI WSAStringToAddressA(LPSTR AddressString, if (!lpAddressLength || !lpAddress) return SOCKET_ERROR; - if (AddressString) + if (!AddressString) { - workBuffer = HeapAlloc( GetProcessHeap(), 0, strlen(AddressString)+1 ); - if (workBuffer) + WSASetLastError(WSAEINVAL); + return SOCKET_ERROR; + } + + if (lpProtocolInfo) + FIXME("ProtocolInfo not implemented.\n"); + + workBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + strlen(AddressString) + 1); + if (!workBuffer) + { + WSASetLastError(WSA_NOT_ENOUGH_MEMORY); + return SOCKET_ERROR; + } + + strcpy(workBuffer, AddressString); + + switch(AddressFamily) + { + case AF_INET: + { + struct in_addr inetaddr; + + /* If lpAddressLength is too small, tell caller the size we need */ + if (*lpAddressLength < sizeof(SOCKADDR_IN)) { - strcpy(workBuffer,AddressString); - switch (AddressFamily) - { - case AF_INET: - /* caller wants to know the size of the socket buffer */ - if (*lpAddressLength < sizeof(SOCKADDR_IN)) - { - *lpAddressLength = sizeof(SOCKADDR_IN); - res = WSAEFAULT; - } - else - { - /* caller wants to translate an AddressString into a SOCKADDR */ - if (lpAddress) - { - memset(lpAddress,0,sizeof(SOCKADDR_IN)); - ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET; - ptrPort = strchr(workBuffer,':'); - if (ptrPort) - { - ((LPSOCKADDR_IN)lpAddress)->sin_port = (WS_u_short)atoi(ptrPort+1); - *ptrPort = '\0'; - } - else - ((LPSOCKADDR_IN)lpAddress)->sin_port = 0; - if (inet_aton(workBuffer, &inetaddr) > 0) - { - ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr; - res = 0; - } - else - res = WSAEINVAL; - } - } - if (lpProtocolInfo) - FIXME("(%s, %x, %p, %p, %p) - ProtocolInfo not implemented!\n", - AddressString, AddressFamily, - lpProtocolInfo, lpAddress, lpAddressLength); + *lpAddressLength = sizeof(SOCKADDR_IN); + res = WSAEFAULT; + break; + } + memset(lpAddress, 0, sizeof(SOCKADDR_IN)); - break; - default: - FIXME("(%s, %x, %p, %p, %p) - AddressFamiliy not implemented!\n", - AddressString, AddressFamily, - lpProtocolInfo, lpAddress, lpAddressLength); - } - HeapFree( GetProcessHeap(), 0, workBuffer ); + ((LPSOCKADDR_IN)lpAddress)->sin_family = AF_INET; + + ptrPort = strchr(workBuffer, ':'); + if(ptrPort) + { + ((LPSOCKADDR_IN)lpAddress)->sin_port = (WS_u_short)atoi(ptrPort+1); + *ptrPort = '\0'; } else - res = WSA_NOT_ENOUGH_MEMORY; + { + ((LPSOCKADDR_IN)lpAddress)->sin_port = 0; + } + + if(inet_aton(workBuffer, &inetaddr) > 0) + { + ((LPSOCKADDR_IN)lpAddress)->sin_addr.WS_s_addr = inetaddr.s_addr; + res = 0; + } + else + res = WSAEINVAL; + + break; + } - else + case AF_INET6: + { + /* If lpAddressLength is too small, tell caller the size we need */ + if (*lpAddressLength < sizeof(SOCKADDR_IN6)) + { + *lpAddressLength = sizeof(SOCKADDR_IN6); + res = WSAEFAULT; + break; + } + FIXME("We don't support IPv6 yet.\n"); + res = WSAEINVAL; + break; + } + default: + /* According to MSDN, only AF_INET and AF_INET6 are supported. */ + TRACE("Unsupported address family specified: %d.\n", AddressFamily); res = WSAEINVAL; + } + + HeapFree(GetProcessHeap(), 0, workBuffer); if (!res) return 0; WSASetLastError(res); diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index cc413206655..7eb6d38c989 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "wine/test.h" #include @@ -1250,6 +1251,7 @@ static void test_WSAStringToAddressA(void) { INT ret, len; SOCKADDR_IN sockaddr; + SOCKADDR_IN6 sockaddr6; int GLE; CHAR address1[] = "0.0.0.0"; @@ -1257,6 +1259,9 @@ static void test_WSAStringToAddressA(void) CHAR address3[] = "255.255.255.255"; CHAR address4[] = "127.127.127.127:65535"; CHAR address5[] = "255.255.255.255:65535"; + CHAR address6[] = "::1"; + CHAR address7[] = "[::1]"; + CHAR address8[] = "[::1]:65535"; len = 0; sockaddr.sin_family = AF_INET; @@ -1308,12 +1313,45 @@ static void test_WSAStringToAddressA(void) ok( (ret == 0 && sockaddr.sin_addr.s_addr == 0xffffffff && sockaddr.sin_port == 0xffff) || (ret == SOCKET_ERROR && (GLE == ERROR_INVALID_PARAMETER || GLE == WSAEINVAL)), "WSAStringToAddressA() failed unexpectedly: %d\n", GLE ); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressA( address6, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressA( address7, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressA( address8, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( (ret == 0 && sockaddr6.sin6_port == 0xffff) || + (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressA() failed for IPv6 address: %d\n", GLE); + } static void test_WSAStringToAddressW(void) { INT ret, len; SOCKADDR_IN sockaddr; + SOCKADDR_IN6 sockaddr6; int GLE; WCHAR address1[] = { '0','.','0','.','0','.','0', 0 }; @@ -1323,6 +1361,9 @@ static void test_WSAStringToAddressW(void) ':', '6', '5', '5', '3', '5', 0 }; WCHAR address5[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', ':', '6', '5', '5', '3', '5', 0 }; + WCHAR address6[] = {':',':','1','\0'}; + WCHAR address7[] = {'[',':',':','1',']','\0'}; + WCHAR address8[] = {'[',':',':','1',']',':','6','5','5','3','5','\0'}; len = 0; sockaddr.sin_family = AF_INET; @@ -1373,6 +1414,38 @@ static void test_WSAStringToAddressW(void) ok( (ret == 0 && sockaddr.sin_addr.s_addr == 0xffffffff && sockaddr.sin_port == 0xffff) || (ret == SOCKET_ERROR && (GLE == ERROR_INVALID_PARAMETER || GLE == WSAEINVAL)), "WSAStringToAddressW() failed unexpectedly: %d\n", GLE ); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressW( address6, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressW( address7, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( ret == 0 || (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); + + len = sizeof(sockaddr6); + memset(&sockaddr6, 0, len); + sockaddr6.sin6_family = AF_INET6; + + ret = WSAStringToAddressW( address8, AF_INET6, NULL, (SOCKADDR*)&sockaddr6, + &len ); + GLE = WSAGetLastError(); + ok( (ret == 0 && sockaddr6.sin6_port == 0xffff) || + (ret == SOCKET_ERROR && GLE == WSAEINVAL), + "WSAStringToAddressW() failed for IPv6 address: %d\n", GLE); + } static VOID WINAPI SelectReadThread(select_thread_params *par) diff --git a/include/Makefile.in b/include/Makefile.in index ee6d1930d66..754df2d26ba 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -282,6 +282,8 @@ SRCDIR_INCLUDES = \ oleauto.h \ olectl.h \ oledlg.h \ + pdh.h \ + pdhmsg.h \ pktdef.h \ poppack.h \ powrprof.h \ @@ -359,6 +361,7 @@ SRCDIR_INCLUDES = \ winnls.h \ winnls32.h \ winnt.h \ + winperf.h \ winreg.h \ winres.h \ winresrc.h \ diff --git a/include/dsdriver.h b/include/dsdriver.h index db48167681e..bb7f4c60316 100644 --- a/include/dsdriver.h +++ b/include/dsdriver.h @@ -52,6 +52,7 @@ typedef struct IDsCaptureDriverBuffer *PIDSCDRIVERBUFFER; #define DSDDESC_USESYSTEMMEMORY 0x00000004 #define DSDDESC_DONTNEEDPRIMARYLOCK 0x00000008 #define DSDDESC_DONTNEEDSECONDARYLOCK 0x00000010 +#define DSDDESC_DONTNEEDWRITELEAD 0x00000020 #define DSDHEAP_NOHEAP 0 #define DSDHEAP_CREATEHEAP 1 diff --git a/include/pdh.h b/include/pdh.h new file mode 100644 index 00000000000..de5dad3db38 --- /dev/null +++ b/include/pdh.h @@ -0,0 +1,186 @@ +/* + * Performance Data Helper + * + * Copyright 2007 Hans Leidekker + * + * 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 _PDH_H_ +#define _PDH_H_ + +#ifdef __WINESRC__ +# include +#else +# include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef LONG PDH_STATUS; +typedef HANDLE PDH_HQUERY; +typedef HANDLE PDH_HCOUNTER; + +#define PDH_MAX_SCALE 7 +#define PDH_MIN_SCALE (-7) + +#define PDH_FMT_LONG 0x00000100 +#define PDH_FMT_DOUBLE 0x00000200 +#define PDH_FMT_LARGE 0x00000400 +#define PDH_FMT_NOSCALE 0x00001000 +#define PDH_FMT_1000 0x00002000 +#define PDH_FMT_NOCAP100 0x00008000 + +typedef struct _PDH_FMT_COUNTERVALUE +{ + DWORD CStatus; + union + { + LONG longValue; + double doubleValue; + LONGLONG largeValue; + LPCSTR AnsiStringValue; + LPCWSTR WideStringValue; + } DUMMYUNIONNAME; +} PDH_FMT_COUNTERVALUE, *PPDH_FMT_COUNTERVALUE; + +typedef struct _PDH_RAW_COUNTER +{ + DWORD CStatus; + FILETIME TimeStamp; + LONGLONG FirstValue; + LONGLONG SecondValue; + DWORD MultiCount; +} PDH_RAW_COUNTER, *PPDH_RAW_COUNTER; + +typedef struct _PDH_COUNTER_PATH_ELEMENTS_A +{ + LPSTR szMachineName; + LPSTR szObjectName; + LPSTR szInstanceName; + LPSTR szParentInstance; + DWORD dwInstanceIndex; + LPSTR szCounterName; +} PDH_COUNTER_PATH_ELEMENTS_A, *PPDH_COUNTER_PATH_ELEMENTS_A; + +typedef struct _PDH_COUNTER_PATH_ELEMENTS_W +{ + LPWSTR szMachineName; + LPWSTR szObjectName; + LPWSTR szInstanceName; + LPWSTR szParentInstance; + DWORD dwInstanceIndex; + LPWSTR szCounterName; +} PDH_COUNTER_PATH_ELEMENTS_W, *PPDH_COUNTER_PATH_ELEMENTS_W; + +typedef struct _PDH_DATA_ITEM_PATH_ELEMENTS_A +{ + LPSTR szMachineName; + GUID ObjectGUID; + DWORD dwItemId; + LPSTR szInstanceName; +} PDH_DATA_ITEM_PATH_ELEMENTS_A, *PPDH_DATA_ITEM_PATH_ELEMENTS_A; + +typedef struct _PDH_DATA_ITEM_PATH_ELEMENTS_W +{ + LPWSTR szMachineName; + GUID ObjectGUID; + DWORD dwItemId; + LPWSTR szInstanceName; +} PDH_DATA_ITEM_PATH_ELEMENTS_W, *PPDH_DATA_ITEM_PATH_ELEMENTS_W; + +typedef struct _PDH_COUNTER_INFO_A +{ + DWORD dwLength; + DWORD dwType; + DWORD CVersion; + DWORD CStatus; + LONG lScale; + LONG lDefaultScale; + DWORD_PTR dwUserData; + DWORD_PTR dwQueryUserData; + LPSTR szFullPath; + union + { + PDH_DATA_ITEM_PATH_ELEMENTS_A DataItemPath; + PDH_COUNTER_PATH_ELEMENTS_A CounterPath; + struct + { + LPSTR szMachineName; + LPSTR szObjectName; + LPSTR szInstanceName; + LPSTR szParentInstance; + DWORD dwInstanceIndex; + LPSTR szCounterName; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + LPSTR szExplainText; + DWORD DataBuffer[1]; +} PDH_COUNTER_INFO_A, *PPDH_COUNTER_INFO_A; + +typedef struct _PDH_COUNTER_INFO_W +{ + DWORD dwLength; + DWORD dwType; + DWORD CVersion; + DWORD CStatus; + LONG lScale; + LONG lDefaultScale; + DWORD_PTR dwUserData; + DWORD_PTR dwQueryUserData; + LPWSTR szFullPath; + union + { + PDH_DATA_ITEM_PATH_ELEMENTS_W DataItemPath; + PDH_COUNTER_PATH_ELEMENTS_W CounterPath; + struct + { + LPWSTR szMachineName; + LPWSTR szObjectName; + LPWSTR szInstanceName; + LPWSTR szParentInstance; + DWORD dwInstanceIndex; + LPWSTR szCounterName; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + LPWSTR szExplainText; + DWORD DataBuffer[1]; +} PDH_COUNTER_INFO_W, *PPDH_COUNTER_INFO_W; + +PDH_STATUS WINAPI PdhAddCounterA(PDH_HQUERY, LPCSTR, DWORD_PTR, PDH_HCOUNTER *); +PDH_STATUS WINAPI PdhAddCounterW(PDH_HQUERY, LPCWSTR, DWORD_PTR, PDH_HCOUNTER *); +#define PdhAddCounter WINELIB_NAME_AW(PdhAddCounter) +PDH_STATUS WINAPI PdhCloseQuery(PDH_HQUERY); +PDH_STATUS WINAPI PdhCollectQueryData(PDH_HQUERY); +PDH_STATUS WINAPI PdhGetCounterInfoA(PDH_HCOUNTER, BOOLEAN, LPDWORD, PPDH_COUNTER_INFO_A); +PDH_STATUS WINAPI PdhGetCounterInfoW(PDH_HCOUNTER, BOOLEAN, LPDWORD, PPDH_COUNTER_INFO_W); +#define PdhGetCounterInfo WINELIB_NAME_AW(PdhGetCounterInfo) +PDH_STATUS WINAPI PdhGetCounterTimeBase(PDH_HCOUNTER, LONGLONG *); +PDH_STATUS WINAPI PdhGetFormattedCounterValue(PDH_HCOUNTER, DWORD, LPDWORD, PPDH_FMT_COUNTERVALUE); +PDH_STATUS WINAPI PdhGetRawCounterValue(PDH_HCOUNTER, LPDWORD, PPDH_RAW_COUNTER); +PDH_STATUS WINAPI PdhOpenQueryA(LPCSTR, DWORD_PTR, PDH_HQUERY *); +PDH_STATUS WINAPI PdhOpenQueryW(LPCWSTR, DWORD_PTR, PDH_HQUERY *); +#define PdhOpenQuery WINELIB_NAME_AW(PdhOpenQuery) +PDH_STATUS WINAPI PdhRemoveCounter(PDH_HCOUNTER); +PDH_STATUS WINAPI PdhSetCounterScaleFactor(PDH_HCOUNTER, LONG); + +#ifdef __cplusplus +} +#endif + +#endif /* _PDH_H_ */ diff --git a/dlls/pdh/pdh_main.c b/include/pdhmsg.h similarity index 58% copy from dlls/pdh/pdh_main.c copy to include/pdhmsg.h index cbc19916a43..3b0812f2097 100644 --- a/dlls/pdh/pdh_main.c +++ b/include/pdhmsg.h @@ -1,7 +1,7 @@ /* - * Performance Data Helper (pdh.dll) + * Performance Data Helper * - * Copyright 2007 Andrey Turkin + * Copyright 2007 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,24 +18,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include +#ifndef _PDH_MSG_H_ +#define _PDH_MSG_H_ -#include "windef.h" -#include "winbase.h" -#include "wine/debug.h" +#define PDH_CSTATUS_VALID_DATA 0x00000000 +#define PDH_MORE_DATA 0x800007d2 +#define PDH_CSTATUS_NO_COUNTER 0xc0000bb9 +#define PDH_MEMORY_ALLOCATION_FAILURE 0xc0000bbb +#define PDH_INVALID_HANDLE 0xc0000bbc +#define PDH_INVALID_ARGUMENT 0xc0000bbd +#define PDH_INVALID_DATA 0xc0000bc6 -WINE_DEFAULT_DEBUG_CHANNEL(pdh); - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - TRACE("(0x%p, %d, %p)\n",hinstDLL,fdwReason,lpvReserved); - - if (fdwReason == DLL_WINE_PREATTACH) return FALSE; /* prefer native version */ - - if (fdwReason == DLL_PROCESS_ATTACH) - { - DisableThreadLibraryCalls( hinstDLL ); - } - - return TRUE; -} +#endif /* _PDH_MSG_H_ */ diff --git a/include/wincrypt.h b/include/wincrypt.h index f4a15da7dcc..4dfbf27bd92 100644 --- a/include/wincrypt.h +++ b/include/wincrypt.h @@ -3127,6 +3127,8 @@ typedef struct _CMSG_ENCRYPTED_ENCODE_INFO #define CMSG_AUTHENTICATED_ATTRIBUTES_FLAG 0x00000008 #define CMSG_CONTENTS_OCTETS_FLAG 0x00000010 #define CMSG_MAX_LENGTH_FLAG 0x00000020 +#define CMSG_CMS_ENCAPSULATED_CONTENT_FLAG 0x00000040 +#define CMSG_CRYPT_RELEASE_CONTEXT_FLAG 0x00008000 #define CMSG_CTRL_VERIFY_SIGNATURE 1 #define CMSG_CTRL_DECRYPT 2 @@ -3189,6 +3191,16 @@ typedef struct _CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA #define CMSG_ENCRYPTED_DIGEST 27 #define CMSG_ENCODED_SIGNER 28 #define CMSG_ENCODED_MESSAGE 29 +#define CMSG_VERSION_PARAM 30 +#define CMSG_ATTR_CERT_COUNT_PARAM 31 +#define CMSG_ATTR_CERT_PARAM 32 +#define CMSG_CMS_RECIPIENT_COUNT_PARAM 33 +#define CMSG_CMS_RECIPIENT_INDEX_PARAM 34 +#define CMSG_CMS_RECIPIENT_ENCRYPTED_KEY_INDEX_PARAM 35 +#define CMSG_CMS_RECIPIENT_INFO_PARAM 36 +#define CMSG_UNPROTECTED_ATTR_PARAM 37 +#define CMSG_SIGNER_CERT_ID_PARAM 38 +#define CMSG_CMS_SIGNER_INFO_PARAM 39 /* function declarations */ /* advapi32.dll */ diff --git a/include/winperf.h b/include/winperf.h new file mode 100644 index 00000000000..eb68ac3404d --- /dev/null +++ b/include/winperf.h @@ -0,0 +1,65 @@ +/* + * Performance Monitor + * + * Copyright 2007 Hans Leidekker + * + * 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 _WINPERF_ +#define _WINPERF_ + +#define PERF_SIZE_DWORD 0x00000000 +#define PERF_SIZE_LARGE 0x00000100 +#define PERF_SIZE_ZERO 0x00000200 +#define PERF_SIZE_VARIABLE_LEN 0x00000300 + +#define PERF_TYPE_NUMBER 0x00000000 +#define PERF_TYPE_COUNTER 0x00000400 +#define PERF_TYPE_TEXT 0x00000800 +#define PERF_TYPE_ZERO 0x00000C00 + +#define PERF_NUMBER_HEX 0x00000000 +#define PERF_NUMBER_DECIMAL 0x00010000 +#define PERF_NUMBER_DEC_1000 0x00020000 + +#define PERF_COUNTER_VALUE 0x00000000 +#define PERF_COUNTER_RATE 0x00010000 +#define PERF_COUNTER_FRACTION 0x00020000 +#define PERF_COUNTER_BASE 0x00030000 +#define PERF_COUNTER_ELAPSED 0x00040000 +#define PERF_COUNTER_QUEUELEN 0x00050000 +#define PERF_COUNTER_HISTOGRAM 0x00060000 +#define PERF_COUNTER_PRECISION 0x00070000 + +#define PERF_TEXT_UNICODE 0x00000000 +#define PERF_TEXT_ASCII 0x00010000 + +#define PERF_TIMER_TICK 0x00000000 +#define PERF_TIMER_100NS 0x00100000 +#define PERF_OBJECT_TIMER 0x00200000 + +#define PERF_DELTA_COUNTER 0x00400000 +#define PERF_DELTA_BASE 0x00800000 +#define PERF_INVERSE_COUNTER 0x01000000 +#define PERF_MULTI_COUNTER 0x02000000 + +#define PERF_DISPLAY_NO_SUFFIX 0x00000000 +#define PERF_DISPLAY_PER_SEC 0x10000000 +#define PERF_DISPLAY_PERCENT 0x20000000 +#define PERF_DISPLAY_SECONDS 0x30000000 +#define PERF_DISPLAY_NOSHOW 0x40000000 + +#endif /* _WINPERF_ */ diff --git a/libs/wpp/ppl.l b/libs/wpp/ppl.l index 58fda7bc30b..eae546516c6 100644 --- a/libs/wpp/ppl.l +++ b/libs/wpp/ppl.l @@ -200,7 +200,6 @@ typedef struct bufferstackentry { /* Include management */ include_state_t incl; char *include_filename; - int pass_data; } bufferstackentry_t; #define ALLOCBLOCKSIZE (1 << 10) /* Allocate these chunks at a time for string-buffers */ @@ -233,7 +232,6 @@ typedef struct macexpstackentry { static void newline(int); static int make_number(int radix, YYSTYPE *val, const char *str, int len); static void put_buffer(const char *s, int len); -static int is_c_h_include(char *fname, int quoted); /* Buffer management */ static void push_buffer(pp_entry_t *ppp, char *filename, char *incname, int pop); static bufferstackentry_t *pop_buffer(void); @@ -272,8 +270,6 @@ static int macexpstackidx = 0; static bufferstackentry_t bufferstack[MAXBUFFERSTACK]; static int bufferstackidx = 0; -static int pass_data=1; - /* * Global variables */ @@ -559,8 +555,6 @@ includelogicentry_t *pp_includelogiclist = NULL; return tDQSTRING; case pp_line: ppy_lval.cptr = get_string(); - if (is_c_h_include(ppy_lval.cptr, 1)) pass_data=0; - else pass_data=1; return tDQSTRING; default: put_string(); @@ -1191,7 +1185,6 @@ static void push_buffer(pp_entry_t *ppp, char *filename, char *incname, int pop) bufferstack[bufferstackidx].ncontinuations = ncontinuations; bufferstack[bufferstackidx].incl = pp_incl_state; bufferstack[bufferstackidx].include_filename = incname; - bufferstack[bufferstackidx].pass_data = pass_data; if(ppp) ppp->expanding = 1; @@ -1254,7 +1247,6 @@ static bufferstackentry_t *pop_buffer(void) } free(pp_incl_state.ppp); pp_incl_state = bufferstack[bufferstackidx].incl; - pass_data = bufferstack[bufferstackidx].pass_data; } } @@ -1410,10 +1402,8 @@ static void put_buffer(const char *s, int len) { if(top_macro()) add_text_to_macro(s, len); - else { - if(pass_data) + else fwrite(s, 1, len, ppy_out); - } } @@ -1422,15 +1412,6 @@ static void put_buffer(const char *s, int len) * Include management *------------------------------------------------------------------------- */ -static int is_c_h_include(char *fname, int quoted) -{ - int sl=strlen(fname); - if (sl < 2 + 2 * quoted) return 0; - if ((toupper(fname[sl-1-quoted])!='H') && (toupper(fname[sl-1-quoted])!='C')) return 0; - if (fname[sl-2-quoted]!='.') return 0; - return 1; -} - void pp_do_include(char *fname, int type) { char *newpath; @@ -1466,12 +1447,10 @@ void pp_do_include(char *fname, int type) pp_incl_state.seen_junk = 0; pp_incl_state.state = 0; pp_incl_state.ppp = NULL; - if (is_c_h_include(newpath, 0)) pass_data=0; - else pass_data=1; if(pp_status.debug) - fprintf(stderr, "pp_do_include: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d ,pass_data=%d\n", - pp_status.input, pp_status.line_number, pp_incl_state.state, pp_incl_state.ppp, pp_incl_state.ifdepth, pass_data); + fprintf(stderr, "pp_do_include: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n", + pp_status.input, pp_status.line_number, pp_incl_state.state, pp_incl_state.ppp, pp_incl_state.ifdepth); ppy__switch_to_buffer(ppy__create_buffer(ppy_in, YY_BUF_SIZE)); fprintf(ppy_out, "# 1 \"%s\" 1%s\n", newpath, type ? "" : " 3"); diff --git a/programs/uninstaller/Ru.rc b/programs/uninstaller/Ru.rc new file mode 100644 index 00000000000..e1f182e1eb8 --- /dev/null +++ b/programs/uninstaller/Ru.rc @@ -0,0 +1,44 @@ +/* + * Uninstaller (Russian Resources) + * + * Copyright 2007 Konstantin Kondratyuk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT + +IDD_UNINSTALLER DIALOG DISCARDABLE 0, 0, 330, 160 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "Óäàëåíèå ïðèëîæåíèé WINE" +FONT 10, "MS Sans Serif" +BEGIN + LTEXT "Ïîæàëóéñòà, âûáåðèòå ïðèëîæåíèå äëÿ óäàëåíèÿ:",IDC_PLEASESELECT,10,10,250,14 + EDITTEXT IDC_FILTER,10,25,250,14,ES_AUTOHSCROLL + LISTBOX IDC_LIST,10,43,250,106,LBS_NOINTEGRALHEIGHT | + LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Óäàëèòü",IDC_UNINSTALL,270,48,50,14 + PUSHBUTTON "&Î ïðîãðàììå",IDC_ABOUT,270,65,50,14 + PUSHBUTTON "&Âûõîä",IDC_EXIT,270,81,50,14 +END + + +STRINGTABLE DISCARDABLE { + IDS_APPNAME, "Óäàëåíèå ïðèëîæåíèé WINE" + IDS_ABOUT, "Óäàëåíèå ïðèëîæåíèé WINE (C) 2005 by Andreas Mohr, Hannu Valtonen and Jonathan Ernst." + IDS_ABOUTTITLE, "Î ïðîãðàììå" + IDS_REGISTRYKEYNOTAVAILABLE, "Íåîáõîäèìàÿ çàïèñü â ðååñòðå îòñóòñòâóåò!" + IDS_UNINSTALLFAILED, "Îøèáêà âûïîëíåíèÿ êîìàíäû óäàëåíèÿ '%s', âîçìîæíî èç-çà ïîòåðè ôàéëîâ ïðèëîæåíèÿ.\r\nÓäàëèòü èíôîðìàöèþ îá óñòàíîâêå èç ðååñòðà?" +} diff --git a/programs/uninstaller/rsrc.rc b/programs/uninstaller/rsrc.rc index 4bc23940dc1..5e64715ca21 100644 --- a/programs/uninstaller/rsrc.rc +++ b/programs/uninstaller/rsrc.rc @@ -39,6 +39,7 @@ #include "No.rc" #include "Pl.rc" #include "Pt.rc" +#include "Ru.rc" #include "Tr.rc" LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL diff --git a/programs/winefile/splitpath.c b/programs/winefile/splitpath.c index 542379a779c..42286eccac8 100644 --- a/programs/winefile/splitpath.c +++ b/programs/winefile/splitpath.c @@ -33,18 +33,18 @@ void _wsplitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* if (drv) { *drv++ = *path++; *drv++ = *path++; - *drv = L'\0'; + *drv = '\0'; } } else if (drv) - *drv = L'\0'; + *drv = '\0'; /* search for end of string or stream separator */ - for(end=path; *end && *end!=L':'; ) + for(end=path; *end && *end!=':'; ) end++; /* search for begin of file extension */ - for(p=end; p>path && *--p!=L'\\' && *p!=L'/'; ) - if (*p == L'.') { + for(p=end; p>path && *--p!='\\' && *p!='/'; ) + if (*p == '.') { end = p; break; } @@ -64,14 +64,14 @@ void _wsplitpath(const WCHAR* path, WCHAR* drv, WCHAR* dir, WCHAR* name, WCHAR* for(s=p; sdata.cFileName; do { - if (!*p || *p==TEXT('\\') || *p==TEXT('/')) + if (!*p || *p == '\\' || *p == '/') return entry; } while(tolower(*p++) == tolower(*q++)); @@ -463,7 +463,7 @@ static Entry* find_entry_win(Entry* dir, LPCTSTR name) q = entry->data.cAlternateFileName; do { - if (!*p || *p==TEXT('\\') || *p==TEXT('/')) + if (!*p || *p == '\\' || *p == '/') return entry; } while(tolower(*p++) == tolower(*q++)); } @@ -486,14 +486,14 @@ static Entry* read_tree_win(Root* root, LPCTSTR path, SORT_ORDER sortOrder, HWND #endif while(entry) { - while(*s && *s!=TEXT('\\') && *s!=TEXT('/')) + while(*s && *s != '\\' && *s != '/') *d++ = *s++; - while(*s==TEXT('\\') || *s==TEXT('/')) + while(*s == '\\' || *s == '/') s++; - *d++ = TEXT('\\'); - *d = TEXT('\0'); + *d++ = '\\'; + *d = '\0'; read_directory(entry, buffer, sortOrder, hwnd); @@ -634,7 +634,7 @@ static Entry* find_entry_unix(Entry* dir, LPCTSTR name) LPCTSTR q = entry->data.cFileName; do { - if (!*p || *p==TEXT('/')) + if (!*p || *p == '/') return entry; } while(*p++ == *q++); } @@ -654,14 +654,14 @@ static Entry* read_tree_unix(Root* root, LPCTSTR path, SORT_ORDER sortOrder, HWN entry->etype = ET_UNIX; while(entry) { - while(*s && *s!=TEXT('/')) + while(*s && *s != '/') *d++ = *s++; - while(*s == TEXT('/')) + while(*s == '/') s++; - *d++ = TEXT('/'); - *d = TEXT('\0'); + *d++ = '/'; + *d = '\0'; read_directory(entry, buffer, sortOrder, hwnd); @@ -1195,8 +1195,8 @@ static int compareExt(const void* arg1, const void* arg2) name1 = fd1->cFileName; name2 = fd2->cFileName; - ext1 = _tcsrchr(name1, TEXT('.')); - ext2 = _tcsrchr(name2, TEXT('.')); + ext1 = _tcsrchr(name1, '.'); + ext2 = _tcsrchr(name2, '.'); if (ext1) ext1++; @@ -1308,7 +1308,7 @@ static void read_directory(Entry* dir, LPCTSTR path, SORT_ORDER sortOrder, HWND while(*s) *d++ = *s++; - *d++ = TEXT('\\'); + *d++ = '\\'; for(entry=dir->down; entry; entry=entry->next) if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { @@ -1331,7 +1331,7 @@ static void read_directory(Entry* dir, LPCTSTR path, SORT_ORDER sortOrder, HWND while(*s) *d++ = *s++; - *d++ = TEXT('/'); + *d++ = '/'; for(entry=dir->down; entry; entry=entry->next) if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { @@ -1353,7 +1353,7 @@ static void read_directory(Entry* dir, LPCTSTR path, SORT_ORDER sortOrder, HWND while(*s) *d++ = *s++; - *d++ = TEXT('\\'); + *d++ = '\\'; for(entry=dir->down; entry; entry=entry->next) if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { @@ -1521,7 +1521,7 @@ static void get_path(Entry* dir, PTSTR path) SFGAOF attribs; HRESULT hr = S_OK; - path[0] = TEXT('\0'); + path[0] = '\0'; attribs = 0; @@ -1546,7 +1546,7 @@ static void get_path(Entry* dir, PTSTR path) name = entry->data.cFileName; s = name; - for(l=0; *s && *s!=TEXT('/') && *s!=TEXT('\\'); s++) + for(l=0; *s && *s != '/' && *s != '\\'; s++) l++; } @@ -1558,10 +1558,10 @@ static void get_path(Entry* dir, PTSTR path) #ifndef _NO_EXTENSIONS if (entry->etype == ET_UNIX) - path[0] = TEXT('/'); + path[0] = '/'; else #endif - path[0] = TEXT('\\'); + path[0] = '\\'; } entry = entry->up; @@ -1576,13 +1576,13 @@ static void get_path(Entry* dir, PTSTR path) if (!level) { #ifndef _NO_EXTENSIONS if (entry->etype == ET_UNIX) - path[len++] = TEXT('/'); + path[len++] = '/'; else #endif - path[len++] = TEXT('\\'); + path[len++] = '\\'; } - path[len] = TEXT('\0'); + path[len] = '\0'; } } @@ -2651,7 +2651,7 @@ static void init_output(HWND hwnd) if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, s1000, 0, b, 16) > 4) Globals.num_sep = b[1]; else - Globals.num_sep = TEXT('.'); + Globals.num_sep = '.'; old_font = SelectObject(hdc, Globals.hfont); GetTextExtentPoint32(hdc, sSpace, 1, &Globals.spaceSize); @@ -2877,12 +2877,12 @@ static int insert_entries(Pane* pane, Entry* dir, LPCTSTR pattern, int filter_fl if (entry->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* don't display entries "." and ".." in the left pane */ - if (pane->treePane && entry->data.cFileName[0]==TEXT('.')) + if (pane->treePane && entry->data.cFileName[0] == '.') if ( #ifndef _NO_EXTENSIONS - entry->data.cFileName[1]==TEXT('\0') || + entry->data.cFileName[1] == '\0' || #endif - (entry->data.cFileName[1]==TEXT('.') && entry->data.cFileName[2]==TEXT('\0'))) + (entry->data.cFileName[1] == '.' && entry->data.cFileName[2] == '\0')) continue; /* filter directories in right pane */ @@ -3015,7 +3015,7 @@ static void format_date(const FILETIME* ft, TCHAR* buffer, int visible_cols) FILETIME lft; int len = 0; - *buffer = TEXT('\0'); + *buffer = '\0'; if (!ft->dwLowDateTime && !ft->dwHighDateTime) return; @@ -3039,7 +3039,7 @@ static void format_date(const FILETIME* ft, TCHAR* buffer, int visible_cols) buffer[len++] = ' '; if (!GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer+len, BUFFER_LEN-len)) - buffer[len] = TEXT('\0'); + buffer[len] = '\0'; } } @@ -3200,11 +3200,11 @@ static void draw_item(Pane* pane, LPDRAWITEMSTRUCT dis, Entry* entry, int calcWi attrs = entry->data.dwFileAttributes; if (attrs & FILE_ATTRIBUTE_DIRECTORY) { - if (entry->data.cFileName[0]==TEXT('.') && entry->data.cFileName[1]==TEXT('.') - && entry->data.cFileName[2]==TEXT('\0')) + if (entry->data.cFileName[0] == '.' && entry->data.cFileName[1] == '.' + && entry->data.cFileName[2] == '\0') img = IMG_FOLDER_UP; #ifndef _NO_EXTENSIONS - else if (entry->data.cFileName[0]==TEXT('.') && entry->data.cFileName[1]==TEXT('\0')) + else if (entry->data.cFileName[0] == '.' && entry->data.cFileName[1] == '\0') img = IMG_FOLDER_CUR; #endif else if ( diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c index 7c537cab4e7..c253a85dbcc 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -33,11 +33,11 @@ * interface, then invoke wineshelllink with the appropriate arguments * to create a KDE/Gnome menu entry for the shortcut. * - * winemenubuilder [ -r ] + * winemenubuilder [ -w ] * - * If the -r parameter is passed, and the shortcut cannot be created, - * this program will add a RunOnce entry to invoke itself at the next - * reboot. This covers the case when a ShortCut is created before the + * If the -w parameter is passed, and the shortcut cannot be created, + * this program will wait for the parent process to finish and then try + * again. This covers the case when a ShortCut is created before the * executable containing its icon. * * TODO @@ -72,6 +72,7 @@ #include #include #include +#include #include "wine/unicode.h" #include "wine/debug.h" @@ -466,9 +467,8 @@ static unsigned short crc16(const char* string) } /* extract an icon from an exe or icon file; helper for IPersistFile_fnSave */ -static char *extract_icon( LPCWSTR path, int index) +static char *extract_icon( LPCWSTR path, int index, BOOL bWait ) { - int nodefault = 1; unsigned short crc; char *iconsdir, *ico_path, *ico_name, *xpm_path; char* s; @@ -520,13 +520,6 @@ static char *extract_icon( LPCWSTR path, int index) return NULL; /* No icon created */ } - /* If icon path begins with a '*' then this is a deferred call */ - if (path[0] == '*') - { - path++; - nodefault = 0; - } - /* Determine the icon base name */ n = WideCharToMultiByte(CP_UNIXCP, 0, path, -1, NULL, 0, NULL, NULL); ico_path = HeapAlloc(GetProcessHeap(), 0, n); @@ -558,7 +551,7 @@ static char *extract_icon( LPCWSTR path, int index) sprintf(xpm_path,"%s/%04x_%s.xpm",iconsdir,crc,ico_name); if (ExtractFromICO( path, xpm_path)) goto end; - if (!nodefault) + if (!bWait) if (create_default_icon( xpm_path, ico_path )) goto end; @@ -571,46 +564,6 @@ static char *extract_icon( LPCWSTR path, int index) return xpm_path; } -static BOOL DeferToRunOnce(LPWSTR link) -{ - HKEY hkey; - LONG r, len; - static const WCHAR szRunOnce[] = { - 'S','o','f','t','w','a','r','e','\\', - 'M','i','c','r','o','s','o','f','t','\\', - 'W','i','n','d','o','w','s','\\', - 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', - 'R','u','n','O','n','c','e',0 - }; - static const WCHAR szFormat[] = { '%','s',' ','"','%','s','"',0 }; - LPWSTR buffer; - WCHAR szExecutable[MAX_PATH]; - - WINE_TRACE( "Deferring icon creation to reboot.\n"); - - len = GetModuleFileNameW( 0, szExecutable, MAX_PATH ); - if (!len || len >= MAX_PATH) return FALSE; - - len = ( lstrlenW( link ) + lstrlenW( szExecutable ) + 4)*sizeof(WCHAR); - buffer = HeapAlloc( GetProcessHeap(), 0, len ); - if( !buffer ) - return FALSE; - - wsprintfW( buffer, szFormat, szExecutable, link ); - - r = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szRunOnce, 0, - NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, NULL); - if ( r == ERROR_SUCCESS ) - { - r = RegSetValueExW(hkey, link, 0, REG_SZ, - (LPBYTE) buffer, (lstrlenW(buffer) + 1)*sizeof(WCHAR)); - RegCloseKey(hkey); - } - HeapFree(GetProcessHeap(), 0, buffer); - - return ! r; -} - /* This escapes \ in filenames */ static LPSTR escape(LPCWSTR arg) { @@ -897,7 +850,7 @@ static HRESULT get_cmdline( IShellLinkW *sl, LPWSTR szPath, DWORD pathSize, return hr; } -static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bAgain ) +static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait ) { static const WCHAR startW[] = {'\\','c','o','m','m','a','n','d', '\\','s','t','a','r','t','.','e','x','e',0}; @@ -907,6 +860,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bAgain ) WCHAR szArgs[INFOTIPSIZE], szIconPath[MAX_PATH]; int iIconId = 0, r = -1; DWORD csidl = -1; + HANDLE hsem = NULL; if ( !link ) { @@ -952,14 +906,14 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bAgain ) /* extract the icon */ if( szIconPath[0] ) - icon_name = extract_icon( szIconPath , iIconId ); + icon_name = extract_icon( szIconPath , iIconId, bWait ); else - icon_name = extract_icon( szPath, iIconId ); + icon_name = extract_icon( szPath, iIconId, bWait ); - /* fail - try once again at reboot time */ + /* fail - try once again after parent process exit */ if( !icon_name ) { - if (bAgain) + if (bWait) { WINE_WARN("Unable to extract icon, deferring.\n"); goto cleanup; @@ -1015,11 +969,23 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bAgain ) escaped_args = escape(szArgs); escaped_description = escape(szDescription); + /* running multiple instances of wineshelllink + at the same time may be dangerous */ + hsem = CreateSemaphoreA( NULL, 1, 1, "winemenubuilder_semaphore"); + if( WAIT_OBJECT_0 != WaitForSingleObject( hsem, INFINITE ) ) + { + WINE_ERR("failed wait for semaphore\n"); + goto cleanup; + } + r = fork_and_wait("wineshelllink", link_name, escaped_path, in_desktop_dir(csidl), escaped_args, icon_name, work_dir ? work_dir : "", escaped_description); + ReleaseSemaphore( hsem, 1, NULL ); + cleanup: + if (hsem) CloseHandle( hsem ); HeapFree( GetProcessHeap(), 0, icon_name ); HeapFree( GetProcessHeap(), 0, work_dir ); HeapFree( GetProcessHeap(), 0, link_name ); @@ -1027,17 +993,60 @@ cleanup: HeapFree( GetProcessHeap(), 0, escaped_path ); HeapFree( GetProcessHeap(), 0, escaped_description ); - if (r) - { + if (r && !bWait) WINE_ERR("failed to fork and exec wineshelllink\n" ); - return FALSE; - } - return TRUE; + return ( r == 0 ); } +static BOOL WaitForParentProcess( void ) +{ + PROCESSENTRY32 procentry; + HANDLE hsnapshot = NULL, hprocess = NULL; + DWORD ourpid = GetCurrentProcessId(); + BOOL ret = FALSE, rc; + + WINE_TRACE("Waiting for parent process\n"); + if ((hsnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 )) == + INVALID_HANDLE_VALUE) + { + WINE_ERR("CreateToolhelp32Snapshot failed, error %d\n", GetLastError()); + goto done; + } + + procentry.dwSize = sizeof(PROCESSENTRY32); + rc = Process32First( hsnapshot, &procentry ); + while (rc) + { + if (procentry.th32ProcessID == ourpid) break; + rc = Process32Next( hsnapshot, &procentry ); + } + if (!rc) + { + WINE_WARN("Unable to find current process id %d when listing processes\n", ourpid); + goto done; + } + + if ((hprocess = OpenProcess( SYNCHRONIZE, FALSE, procentry.th32ParentProcessID )) == + NULL) + { + WINE_WARN("OpenProcess failed pid=%d, error %d\n", procentry.th32ParentProcessID, + GetLastError()); + goto done; + } + + if (WaitForSingleObject( hprocess, INFINITE ) == WAIT_OBJECT_0) + ret = TRUE; + else + WINE_ERR("Unable to wait for parent process, error %d\n", GetLastError()); + +done: + if (hprocess) CloseHandle( hprocess ); + if (hsnapshot) CloseHandle( hsnapshot ); + return ret; +} -static BOOL Process_Link( LPCWSTR linkname, BOOL bAgain ) +static BOOL Process_Link( LPCWSTR linkname, BOOL bWait ) { IShellLinkW *sl; IPersistFile *pf; @@ -1045,7 +1054,7 @@ static BOOL Process_Link( LPCWSTR linkname, BOOL bAgain ) WCHAR fullname[MAX_PATH]; DWORD len; - WINE_TRACE("%s, again %d\n", wine_dbgstr_w(linkname), bAgain); + WINE_TRACE("%s, wait %d\n", wine_dbgstr_w(linkname), bWait); if( !linkname[0] ) { @@ -1086,12 +1095,13 @@ static BOOL Process_Link( LPCWSTR linkname, BOOL bAgain ) if( SUCCEEDED( r ) ) { /* If something fails (eg. Couldn't extract icon) - * defer this menu entry to reboot via runonce + * wait for parent process and try again */ - if( ! InvokeShellLinker( sl, fullname, bAgain ) && bAgain ) - DeferToRunOnce( fullname ); - else - WINE_TRACE("Success.\n"); + if( ! InvokeShellLinker( sl, fullname, bWait ) && bWait ) + { + WaitForParentProcess(); + InvokeShellLinker( sl, fullname, FALSE ); + } } IPersistFile_Release( pf ); @@ -1146,25 +1156,16 @@ static CHAR *next_token( LPSTR *p ) int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show) { LPSTR token = NULL, p; - BOOL bAgain = FALSE; - HANDLE hsem = CreateSemaphoreA( NULL, 1, 1, "winemenubuilder_semaphore"); + BOOL bWait = FALSE; int ret = 0; - /* running multiple instances of wineshelllink - at the same time may be dangerous */ - if( WAIT_OBJECT_0 != WaitForSingleObject( hsem, INFINITE ) ) - { - CloseHandle(hsem); - return FALSE; - } - for( p = cmdline; p && *p; ) { token = next_token( &p ); if( !token ) break; - if( !lstrcmpA( token, "-r" ) ) - bAgain = TRUE; + if( !lstrcmpA( token, "-w" ) ) + bWait = TRUE; else if( token[0] == '-' ) { WINE_ERR( "unknown option %s\n",token); @@ -1174,7 +1175,7 @@ int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show WCHAR link[MAX_PATH]; MultiByteToWideChar( CP_ACP, 0, token, -1, link, sizeof(link)/sizeof(WCHAR) ); - if( !Process_Link( link, bAgain ) ) + if( !Process_Link( link, bWait ) ) { WINE_ERR( "failed to build menu item for %s\n",token); ret = 1; @@ -1182,8 +1183,5 @@ int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show } } - ReleaseSemaphore( hsem, 1, NULL ); - CloseHandle( hsem ); - return ret; } diff --git a/tools/wine.inf b/tools/wine.inf index 78ced6d63d1..30e7ee00ed0 100644 --- a/tools/wine.inf +++ b/tools/wine.inf @@ -254,6 +254,7 @@ HKLM,Software\Microsoft\DirectPlay\Service Providers\Serial Connection For Direc HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"ComSpec",,"%11%\cmd.exe" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"PATH",2,"%11%;%10%" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"ProgramFiles",,"%16422%" +HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"SystemDrive",2,"c:" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"SYSTEMROOT",,"%10%" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"TEMP",,"%10%\temp" HKLM,System\CurrentControlSet\Control\Session Manager\Environment,"TMP",,"%10%\temp" diff --git a/tools/wrc/parser.l b/tools/wrc/parser.l index f9034a5451a..4b0a7db24a6 100644 --- a/tools/wrc/parser.l +++ b/tools/wrc/parser.l @@ -76,10 +76,7 @@ /* Exclusive comment eating... */ %x comment /* Set when stripping c-junk */ -%x pp_stripe -%x pp_strips -%x pp_stripp -%x pp_stripp_final +%x pp_cstrip /* Set when scanning #line style directives */ %x pp_line /* Set when scanning #pragma */ @@ -87,7 +84,7 @@ %x pp_code_page %option stack -%option nounput noyy_top_state +%option nounput noyy_top_state noyywrap %option 8bit never-interactive %option prefix="parser_" @@ -128,9 +125,6 @@ static int cbufalloc = 0; static WCHAR *wbuffer; static int wbufidx; static int wbufalloc = 0; -static int stripslevel = 0; /* Count {} during pp_strips/pp_stripe mode */ -static int stripplevel = 0; /* Count () during pp_strips mode */ -static int cjunk_tagline; /* Where did we start stripping (helps error tracking) */ static int current_codepage = -1; /* use language default */ @@ -321,10 +315,10 @@ static struct keyword *iskeyword(char *kw) * because we only want to know the linenumber and * filename. */ -^{ws}*\#{ws}*pragma{ws}+ yy_push_state(pp_pragma); -^{ws}*\#{ws}* yy_push_state(pp_line); +^{ws}*\#{ws}*pragma{ws}+ yy_push_state(pp_pragma); +^{ws}*\#{ws}* yy_push_state(pp_line); [^\n]* { - int lineno; + int lineno, len; char *cptr; char *fname; yy_pop_state(); @@ -341,6 +335,12 @@ static struct keyword *iskeyword(char *kw) *cptr = '\0'; line_number = lineno - 1; /* We didn't read the newline */ input_name = xstrdup(fname); + /* ignore contents of C include files */ + len = strlen(input_name); + if (len > 1 && !strcasecmp( input_name + len - 2, ".h" )) + BEGIN(pp_cstrip); + else + BEGIN(INITIAL); } code_page[^\n]* yyless(9); yy_pop_state(); yy_push_state(pp_code_page); @@ -366,30 +366,8 @@ static struct keyword *iskeyword(char *kw) * into account braces {} for structures, * classes and enums. */ -\{ stripslevel++; -\} stripslevel--; -; if(!stripslevel) yy_pop_state(); -\/[^*\n] ; /* To catch comments */ -[^\{\};\n#/]* ; /* Ignore rest */ -\n line_number++; char_number = 1; - -\( stripplevel++; -\) { - stripplevel--; - if(!stripplevel) - { - yy_pop_state(); - yy_push_state(pp_stripp_final); - } - } -\/[^*\n] ; /* To catch comments */ -[^\(\);\n#/]* ; /* Ignore rest */ -\n line_number++; char_number = 1; - -{ws}* ; /* Ignore */ -; yy_pop_state(); /* Kill the semicolon */ -\n line_number++; char_number = 1; yy_pop_state(); -. yyless(0); yy_pop_state(); +\n line_number++; char_number = 1; +. ; /* ignore */ \{ return tBEGIN; \} return tEND; @@ -546,7 +524,7 @@ L\" { * Comment stripping * Should never occur after preprocessing */ -"/*" { +"/*" { yy_push_state(comment); save_wanted_id = wanted_id; if(!no_preprocess) @@ -574,13 +552,6 @@ L\" { . return yytext[0]; -<> { - if(YY_START == pp_strips || YY_START == pp_stripe || YY_START == pp_stripp || YY_START == pp_stripp_final) - parser_error("Unexpected end of file during c-junk scanning (started at %d)", cjunk_tagline); - else - yyterminate(); - } - <*>.|\n { /* Catch all rule to find any unmatched text */ if(*yytext == '\n') @@ -588,25 +559,12 @@ L\" { line_number++; char_number = 1; } - parser_warning("Unmatched text '%c' (0x%02x) YY_START=%d stripslevel=%d", - isprint(*yytext & 0xff) ? *yytext : '.', *yytext, YY_START,stripslevel); + parser_warning("Unmatched text '%c' (0x%02x) YY_START=%d", + isprint(*yytext & 0xff) ? *yytext : '.', *yytext, YY_START); } %% -#ifndef parser_wrap -int parser_wrap(void) -{ -#if 0 - if(bufferstackidx > 0) - { - return 0; - } -#endif - return 1; -} -#endif - /* These dup functions copy the enclosed '\0' from * the resource string. */ -- 2.11.4.GIT