Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
Re: [PATCH v3 0/5] MR139: winegstreamer: Implement video plane alignment for the H264 decoder. - approved
by Zebediah Figura (@zfigura)
This merge request was approved by Zebediah Figura.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/139
June 2, 2022
[PATCH v2] ws2_32: Add WSAConnectByName() functions
by Julian Klemann
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50941
Signed-off-by: Julian Klemann <jklemann(a)codeweavers.com>
---
v2: Add WS prefix to include/winsock2.h, change %llu to %Iu for sizeof
---
dlls/ws2_32/socket.c | 168 +++++++++++++++++++++++++++++++++++
dlls/ws2_32/tests/sock.c | 151 +++++++++++++++++++++++++++++++
dlls/ws2_32/ws2_32.spec | 2 +
dlls/ws2_32/ws2_32_private.h | 12 +++
include/winsock2.h | 3 +
5 files changed, 336 insertions(+)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 88089fa8d74..6a93d00730a 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -1284,6 +1284,174 @@ static BOOL WINAPI WS2_ConnectEx( SOCKET s, const struct sockaddr *name, int nam
}
+/***********************************************************************
+ * WSAConnectByNameA (WS2_32.@)
+ */
+BOOL WINAPI WSAConnectByNameA(SOCKET s, const char *node_name, const char *service_name,
+ DWORD *local_addr_len, struct sockaddr *local_addr,
+ DWORD *remote_addr_len, struct sockaddr *remote_addr,
+ const struct timeval *timeout, WSAOVERLAPPED *reserved)
+{
+ WSAPROTOCOL_INFOA proto_info;
+ WSAPOLLFD pollout;
+ struct addrinfo *service, hints;
+ int ret, proto_len, sockaddr_size, sockname_size, sock_err, int_len;
+
+ TRACE("socket %#Ix, node_name %s, service_name %s, local_addr_len %p, local_addr %p, \
+ remote_addr_len %p, remote_addr %p, timeout %p, reserved %p\n",
+ s, debugstr_a(node_name), debugstr_a(service_name), local_addr_len, local_addr,
+ remote_addr_len, remote_addr, timeout, reserved );
+
+ if (!node_name || !service_name || reserved)
+ {
+ SetLastError(WSAEINVAL);
+ return FALSE;
+ }
+
+ if (!s)
+ {
+ SetLastError(WSAENOTSOCK);
+ return FALSE;
+ }
+
+ if (timeout)
+ FIXME("WSAConnectByName timeout stub\n");
+
+ proto_len = sizeof(WSAPROTOCOL_INFOA);
+ ret = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *)&proto_info, &proto_len);
+ if (ret)
+ return FALSE;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_socktype = proto_info.iSocketType;
+ hints.ai_family = proto_info.iAddressFamily;
+ hints.ai_protocol = proto_info.iProtocol;
+ ret = getaddrinfo(node_name, service_name, &hints, &service);
+ if (ret)
+ return FALSE;
+
+ if (proto_info.iSocketType != SOCK_STREAM)
+ {
+ freeaddrinfo(service);
+ SetLastError(WSAEFAULT);
+ return FALSE;
+ }
+
+ switch (proto_info.iAddressFamily)
+ {
+ case AF_INET:
+ sockaddr_size = sizeof(SOCKADDR_IN);
+ break;
+ case AF_INET6:
+ sockaddr_size = sizeof(SOCKADDR_IN6);
+ break;
+ default:
+ freeaddrinfo(service);
+ SetLastError(WSAENOTSOCK);
+ return FALSE;
+ }
+
+ ret = connect(s, service->ai_addr, sockaddr_size);
+ if (ret)
+ {
+ freeaddrinfo(service);
+ return FALSE;
+ }
+
+ pollout.fd = s;
+ pollout.events = POLLWRNORM;
+ ret = WSAPoll(&pollout, 1, -1);
+ if (ret == SOCKET_ERROR)
+ {
+ freeaddrinfo(service);
+ return FALSE;
+ }
+ if (pollout.revents & (POLLERR | POLLHUP | POLLNVAL))
+ {
+ freeaddrinfo(service);
+ int_len = sizeof(int);
+ ret = getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&sock_err, &int_len);
+ if (ret == SOCKET_ERROR)
+ return FALSE;
+ SetLastError(sock_err);
+ return FALSE;
+ }
+
+ if (remote_addr_len && remote_addr)
+ {
+ if (*remote_addr_len >= sockaddr_size)
+ {
+ memcpy(remote_addr, service->ai_addr, sockaddr_size);
+ *remote_addr_len = sockaddr_size;
+ }
+ else
+ {
+ freeaddrinfo(service);
+ SetLastError(WSAEFAULT);
+ return FALSE;
+ }
+ }
+
+ freeaddrinfo(service);
+
+ if (local_addr_len && local_addr)
+ {
+ if (*local_addr_len >= sockaddr_size)
+ {
+ sockname_size = sockaddr_size;
+ ret = getsockname(s, local_addr, &sockname_size);
+ if (ret)
+ return FALSE;
+ if (proto_info.iAddressFamily == AF_INET6)
+ ((SOCKADDR_IN6 *)local_addr)->sin6_port = 0;
+ else
+ ((SOCKADDR_IN *)local_addr)->sin_port = 0;
+ *local_addr_len = sockaddr_size;
+ }
+ else
+ {
+ SetLastError(WSAEFAULT);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * WSAConnectByNameW (WS2_32.@)
+ */
+BOOL WINAPI WSAConnectByNameW(SOCKET s, const WCHAR *node_name, const WCHAR *service_name,
+ DWORD *local_addr_len, struct sockaddr *local_addr,
+ DWORD *remote_addr_len, struct sockaddr *remote_addr,
+ const struct timeval *timeout, WSAOVERLAPPED *reserved)
+{
+ char *node_nameA, *service_nameA;
+ BOOL ret;
+
+ if (!node_name || !service_name)
+ {
+ SetLastError(WSAEINVAL);
+ return FALSE;
+ }
+
+ node_nameA = strdupWtoA(node_name);
+ service_nameA = strdupWtoA(service_name);
+ if (!node_nameA || !service_nameA)
+ {
+ SetLastError(WSAENOBUFS);
+ return FALSE;
+ }
+
+ ret = WSAConnectByNameA(s, node_nameA, service_nameA, local_addr_len, local_addr,
+ remote_addr_len, remote_addr, timeout, reserved);
+ free(node_nameA);
+ free(service_nameA);
+ return ret;
+}
+
+
static BOOL WINAPI WS2_DisconnectEx( SOCKET s, OVERLAPPED *overlapped, DWORD flags, DWORD reserved )
{
IO_STATUS_BLOCK iosb, *piosb = &iosb;
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index bdb683e6796..4a4a3a84e51 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -3197,6 +3197,156 @@ static void test_WSADuplicateSocket(void)
closesocket(source);
}
+static void test_WSAConnectByName(void)
+{
+ SOCKET s;
+ SOCKADDR_IN local_addr = {0}, remote_addr = {0},
+ sock_addr = {0}, peer_addr = {0};
+ DWORD local_len, remote_len, conn_ctx;
+ int ret, err, sock_len, peer_len;
+ WSAOVERLAPPED overlap;
+ struct addrinfo *first_addrinfo, first_hints;
+
+ conn_ctx = TRUE;
+
+ /* First call of getaddrinfo fails on w8adm */
+ first_addrinfo = NULL;
+ memset(&first_hints, 0, sizeof(struct addrinfo));
+ first_hints.ai_socktype = SOCK_STREAM;
+ first_hints.ai_family = AF_INET;
+ first_hints.ai_protocol = IPPROTO_TCP;
+ getaddrinfo("winehq.org", "http", &first_hints, &first_addrinfo);
+ if (first_addrinfo)
+ freeaddrinfo(first_addrinfo);
+ SetLastError(0xdeadbeef);
+
+ /* Fill all fields */
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ local_len = remote_len = sizeof(SOCKADDR_IN);
+ ret = WSAConnectByNameA(s, "winehq.org", "http", &local_len, (struct sockaddr *)&local_addr,
+ &remote_len, (struct sockaddr *)&remote_addr, NULL, NULL);
+ ok(ret, "WSAConnectByNameA should have succeeded, error %u\n", WSAGetLastError());
+ setsockopt(s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, (char *)&conn_ctx, sizeof(DWORD));
+ sock_len = peer_len = sizeof(SOCKADDR_IN);
+ ret = getsockname(s, (struct sockaddr *)&sock_addr, &sock_len);
+ ok(!ret, "getsockname should have succeeded, error %u\n", WSAGetLastError());
+ ret = getpeername(s, (struct sockaddr *)&peer_addr, &peer_len);
+ ok(!ret, "getpeername should have succeeded, error %u\n", WSAGetLastError());
+ ok(sock_len == sizeof(SOCKADDR_IN), "got sockname size of %d\n", sock_len);
+ ok(peer_len == sizeof(SOCKADDR_IN), "got peername size of %d\n", peer_len);
+ ok(local_len == sizeof(SOCKADDR_IN), "got local size of %lu\n", local_len);
+ ok(remote_len == sizeof(SOCKADDR_IN), "got remote size of %lu\n", remote_len);
+ ok(!local_addr.sin_port, "local_addr has non-zero sin_port: %hu.\n", local_addr.sin_port);
+ ok(!memcmp(&sock_addr.sin_addr, &local_addr.sin_addr, sizeof(struct in_addr)),
+ "local_addr did not receive data.\n");
+ ok(!memcmp(&peer_addr, &remote_addr, sizeof(SOCKADDR_IN)), "remote_addr did not receive data.\n");
+ closesocket(s);
+
+ /* Passing NULL length but a pointer to a sockaddr */
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ local_len = remote_len = sizeof(SOCKADDR_IN);
+ memset(&local_addr, 0, sizeof(SOCKADDR_IN));
+ memset(&remote_addr, 0, sizeof(SOCKADDR_IN));
+ memset(&sock_addr, 0, sizeof(SOCKADDR_IN));
+ memset(&peer_addr, 0, sizeof(SOCKADDR_IN));
+ ret = WSAConnectByNameA(s, "winehq.org", "http", NULL, (struct sockaddr *)&local_addr,
+ NULL, (struct sockaddr *)&remote_addr, NULL, NULL);
+ ok(ret, "WSAConnectByNameA should have succeeded, error %u\n", WSAGetLastError());
+ setsockopt(s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, (char *)&conn_ctx, sizeof(DWORD));
+ sock_len = peer_len = sizeof(SOCKADDR_IN);
+ ret = getsockname(s, (struct sockaddr *)&sock_addr, &sock_len);
+ ok(!ret, "getsockname should have succeeded, error %u\n", WSAGetLastError());
+ ret = getpeername(s, (struct sockaddr *)&peer_addr, &peer_len);
+ ok(!ret, "getpeername should have succeeded, error %u\n", WSAGetLastError());
+ ok(sock_len == sizeof(SOCKADDR_IN), "got sockname size of %d\n", sock_len);
+ ok(peer_len == sizeof(SOCKADDR_IN), "got peername size of %d\n", peer_len);
+ ok(!local_addr.sin_family, "local_addr received data.\n");
+ ok(!remote_addr.sin_family, "remote_addr received data.\n");
+ closesocket(s);
+
+ /* Passing NULLs for node or service */
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ ret = WSAConnectByNameA(s, NULL, "http", NULL, NULL, NULL, NULL, NULL, NULL);
+ err = WSAGetLastError();
+ ok(!ret, "WSAConnectByNameA should have failed\n");
+ ok(err == WSAEINVAL, "expected error %u (WSAEINVAL), got %u\n", WSAEINVAL, err);
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ closesocket(s);
+ ret = WSAConnectByNameA(s, "winehq.org", NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ err = WSAGetLastError();
+ ok(!ret, "WSAConnectByNameA should have failed\n");
+ ok(err == WSAEINVAL, "expected error %u (WSAEINVAL), got %u\n", WSAEINVAL, err);
+ closesocket(s);
+
+ /* Passing NULL for the addresses and address lengths */
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ ret = WSAConnectByNameA(s, "winehq.org", "http", NULL, NULL, NULL, NULL, NULL, NULL);
+ ok(ret, "WSAConnectByNameA should have succeeded, error %u\n", WSAGetLastError());
+ closesocket(s);
+
+ /* Passing NULL for the addresses and passing correct lengths */
+ local_len = remote_len = sizeof(SOCKADDR_IN);
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ ret = WSAConnectByNameA(s, "winehq.org", "http", &local_len, NULL,
+ &remote_len, NULL, NULL, NULL);
+ ok(ret, "WSAConnectByNameA should have succeeded, error %u\n", WSAGetLastError());
+ ok(local_len == sizeof(SOCKADDR_IN), "local_len should have been %Iu, got %ld\n", sizeof(SOCKADDR_IN),
+ local_len);
+ ok(remote_len == sizeof(SOCKADDR_IN), "remote_len should have been %Iu, got %ld\n", sizeof(SOCKADDR_IN),
+ remote_len);
+ closesocket(s);
+
+ /* Passing addresses and passing short lengths */
+ local_len = remote_len = 3;
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ ret = WSAConnectByNameA(s, "winehq.org", "http", &local_len, (struct sockaddr *)&local_addr,
+ &remote_len, (struct sockaddr *)&remote_addr, NULL, NULL);
+ err = WSAGetLastError();
+ ok(!ret, "WSAConnectByNameA should have failed\n");
+ ok(err == WSAEFAULT, "expected error %u (WSAEFAULT), got %u\n", WSAEFAULT, err);
+ ok(local_len == 3, "local_len should have been 3, got %ld\n", local_len);
+ ok(remote_len == 3, "remote_len should have been 3, got %ld\n", remote_len);
+ closesocket(s);
+
+ /* Passing addresses and passing long lengths */
+ local_len = remote_len = 50;
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ ret = WSAConnectByNameA(s, "winehq.org", "http", &local_len, (struct sockaddr *)&local_addr,
+ &remote_len, (struct sockaddr *)&remote_addr, NULL, NULL);
+ ok(ret, "WSAConnectByNameA should have succeeded, error %u\n", WSAGetLastError());
+ ok(local_len == sizeof(SOCKADDR_IN), "local_len should have been %Iu, got %ld\n", sizeof(SOCKADDR_IN),
+ local_len);
+ ok(remote_len == sizeof(SOCKADDR_IN), "remote_len should have been %Iu, got %ld\n", sizeof(SOCKADDR_IN),
+ remote_len);
+ closesocket(s);
+
+ /* Unknown service */
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ ret = WSAConnectByNameA(s, "winehq.org", "nonexistentservice", NULL, NULL, NULL, NULL, NULL, NULL);
+ err = WSAGetLastError();
+ ok(!ret, "WSAConnectByNameA should have failed\n");
+ ok(err == WSATYPE_NOT_FOUND, "expected error %u (WSATYPE_NOT_FOUND), got %u\n",
+ WSATYPE_NOT_FOUND, err);
+ closesocket(s);
+
+ /* Connecting with a UDP socket */
+ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ ret = WSAConnectByNameA(s, "winehq.org", "https", NULL, NULL, NULL, NULL, NULL, NULL);
+ err = WSAGetLastError();
+ ok(!ret, "WSAConnectByNameA should have failed\n");
+ ok(err == WSAEINVAL || err == WSAEFAULT, "expected error %u (WSAEINVAL) or %u (WSAEFAULT), got %u\n",
+ WSAEINVAL, WSAEFAULT, err); /* WSAEFAULT win10 >= 1809 */
+ closesocket(s);
+
+ /* Passing non-null as the reserved parameter */
+ s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ ret = WSAConnectByNameA(s, "winehq.org", "http", NULL, NULL, NULL, NULL, NULL, &overlap);
+ err = WSAGetLastError();
+ ok(!ret, "WSAConnectByNameA should have failed\n");
+ ok(err == WSAEINVAL, "expected error %u (WSAEINVAL), got %u\n", WSAEINVAL, err);
+ closesocket(s);
+}
+
static void test_WSAEnumNetworkEvents(void)
{
SOCKET s, s2;
@@ -12573,6 +12723,7 @@ START_TEST( sock )
test_WSASocket();
test_WSADuplicateSocket();
+ test_WSAConnectByName();
test_WSAEnumNetworkEvents();
test_errors();
diff --git a/dlls/ws2_32/ws2_32.spec b/dlls/ws2_32/ws2_32.spec
index 1fbd8c55c75..6a07895d2f6 100644
--- a/dlls/ws2_32/ws2_32.spec
+++ b/dlls/ws2_32/ws2_32.spec
@@ -68,6 +68,8 @@
@ stdcall WSAAddressToStringW(ptr long ptr ptr ptr)
@ stdcall WSACloseEvent(long)
@ stdcall WSAConnect(long ptr long ptr ptr ptr ptr)
+@ stdcall WSAConnectByNameA(long str str ptr ptr ptr ptr ptr ptr)
+@ stdcall WSAConnectByNameW(long str str ptr ptr ptr ptr ptr ptr)
@ stdcall WSACreateEvent ()
@ stdcall WSADuplicateSocketA(long long ptr)
@ stdcall WSADuplicateSocketW(long long ptr)
diff --git a/dlls/ws2_32/ws2_32_private.h b/dlls/ws2_32/ws2_32_private.h
index f6b6ecc7eba..b21936a34e1 100644
--- a/dlls/ws2_32/ws2_32_private.h
+++ b/dlls/ws2_32/ws2_32_private.h
@@ -61,6 +61,18 @@
0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \
static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 }
+static inline char *strdupWtoA( const WCHAR *str )
+{
+ char *ret = NULL;
+ if (str)
+ {
+ DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
+ if ((ret = malloc( len )))
+ WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
+ }
+ return ret;
+}
+
static const char magic_loopback_addr[] = {127, 12, 34, 56};
const char *debugstr_sockaddr( const struct sockaddr *addr ) DECLSPEC_HIDDEN;
diff --git a/include/winsock2.h b/include/winsock2.h
index f1d43acad40..86050025074 100644
--- a/include/winsock2.h
+++ b/include/winsock2.h
@@ -1157,6 +1157,9 @@ int WINAPI WSACancelBlockingCall(void);
int WINAPI WSACleanup(void);
BOOL WINAPI WSACloseEvent(WSAEVENT);
int WINAPI WSAConnect(SOCKET,const struct WS(sockaddr)*,int,LPWSABUF,LPWSABUF,LPQOS,LPQOS);
+BOOL WINAPI WSAConnectByNameA(SOCKET,const char *,const char *,DWORD *,struct WS(sockaddr) *,DWORD *,struct WS(sockaddr) *,const struct WS(timeval) *,WSAOVERLAPPED *);
+BOOL WINAPI WSAConnectByNameW(SOCKET,const WCHAR *,const WCHAR *,DWORD *,struct WS(sockaddr) *,DWORD *,struct WS(sockaddr) *,const struct WS(timeval) *,WSAOVERLAPPED *);
+#define WSAConnectByName WINELIB_NAME_AW(WSAConnectByName)
WSAEVENT WINAPI WSACreateEvent(void);
INT WINAPI WSADuplicateSocketA(SOCKET,DWORD,LPWSAPROTOCOL_INFOA);
INT WINAPI WSADuplicateSocketW(SOCKET,DWORD,LPWSAPROTOCOL_INFOW);
--
2.36.1
June 2, 2022
Re: [PATCH 0/4] MR37: user32/tests: Fix message tests that fail on Vista, Win2003, or Win2008
by Rémi Bernon
I think the issue here is, I think, that we don't really care anymore about these versions of Windows, and adding optional messages to match them is only making the message sequences more complex, and less easy to correctly implement.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/37#note_1524
June 2, 2022
Re: [PATCH 0/9] MR176: windows.media.speech: Bring synthesizer.c more in line with the rest of the Dll. - approved
by Rémi Bernon
This merge request was approved by Rémi Bernon.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/176
June 2, 2022
[PATCH v4 6/6] jscript: Don't allow construction on builtin methods.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
v4: Fix error.
dlls/jscript/function.c | 2 ++
dlls/jscript/tests/api.js | 1 +
2 files changed, 3 insertions(+)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c
index 984eebf..bf152e2 100644
--- a/dlls/jscript/function.c
+++ b/dlls/jscript/function.c
@@ -619,6 +619,8 @@ static HRESULT NativeFunction_call(script_ctx_t *ctx, FunctionInstance *func, js
{
NativeFunction *function = (NativeFunction*)func;
+ if((flags & DISPATCH_CONSTRUCT) && !(function->function.flags & PROPF_CONSTR))
+ return JS_E_INVALID_ACTION;
return function->proc(ctx, vthis, flags & ~DISPATCH_JSCRIPT_INTERNAL_MASK, argc, argv, r);
}
diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js
index 1368f39..123665c 100644
--- a/dlls/jscript/tests/api.js
+++ b/dlls/jscript/tests/api.js
@@ -2622,6 +2622,7 @@ testException(function() {"test" in nullDisp;}, "E_OBJECT_EXPECTED");
testException(function() {new 3;}, "E_UNSUPPORTED_ACTION");
testException(function() {new null;}, "E_OBJECT_EXPECTED");
testException(function() {new nullDisp;}, "E_NO_PROPERTY");
+testException(function() {new Math.max(5);}, "E_UNSUPPORTED_ACTION");
testException(function() {new VBArray();}, "E_NOT_VBARRAY");
testException(function() {new VBArray(new VBArray(createArray()));}, "E_NOT_VBARRAY");
testException(function() {VBArray.prototype.lbound.call(new Object());}, "E_NOT_VBARRAY");
--
2.34.1
June 2, 2022
[PATCH v4 5/6] jscript: Release all globals when the script is uninitialized.
by Gabriel Ivăncescu
Most of these globals were leaking before as they were never freed at all.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/jscript.c | 31 ++++++++++---------------
dlls/jscript/jscript.h | 50 ++++++++++++++++++++++------------------
dlls/jscript/tests/run.c | 1 -
3 files changed, 40 insertions(+), 42 deletions(-)
diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c
index d6028e6..8a54f32 100644
--- a/dlls/jscript/jscript.c
+++ b/dlls/jscript/jscript.c
@@ -91,6 +91,17 @@ void script_release(script_ctx_t *ctx)
heap_free(ctx);
}
+static void script_globals_release(script_ctx_t *ctx)
+{
+ unsigned i;
+ for(i = 0; i < ARRAY_SIZE(ctx->global_objects); i++) {
+ if(ctx->global_objects[i]) {
+ jsdisp_release(ctx->global_objects[i]);
+ ctx->global_objects[i] = NULL;
+ }
+ }
+}
+
static void change_state(JScript *This, SCRIPTSTATE state)
{
if(This->ctx->state == state)
@@ -483,25 +494,7 @@ static void decrease_state(JScript *This, SCRIPTSTATE state)
This->ctx->site = NULL;
}
- if(This->ctx->map_prototype) {
- jsdisp_release(This->ctx->map_prototype);
- This->ctx->map_prototype = NULL;
- }
-
- if(This->ctx->set_prototype) {
- jsdisp_release(This->ctx->set_prototype);
- This->ctx->set_prototype = NULL;
- }
-
- if(This->ctx->object_prototype) {
- jsdisp_release(This->ctx->object_prototype);
- This->ctx->object_prototype = NULL;
- }
-
- if(This->ctx->global) {
- jsdisp_release(This->ctx->global);
- This->ctx->global = NULL;
- }
+ script_globals_release(This->ctx);
/* FALLTHROUGH */
case SCRIPTSTATE_UNINITIALIZED:
change_state(This, state);
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 000bcc2..0f8baea 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -387,29 +387,35 @@ struct _script_ctx_t {
DWORD last_match_index;
DWORD last_match_length;
- jsdisp_t *global;
- jsdisp_t *function_constr;
- jsdisp_t *array_constr;
- jsdisp_t *bool_constr;
- jsdisp_t *date_constr;
- jsdisp_t *enumerator_constr;
- jsdisp_t *error_constr;
- jsdisp_t *eval_error_constr;
- jsdisp_t *range_error_constr;
- jsdisp_t *reference_error_constr;
- jsdisp_t *regexp_error_constr;
- jsdisp_t *syntax_error_constr;
- jsdisp_t *type_error_constr;
- jsdisp_t *uri_error_constr;
- jsdisp_t *number_constr;
- jsdisp_t *object_constr;
- jsdisp_t *object_prototype;
- jsdisp_t *regexp_constr;
- jsdisp_t *string_constr;
- jsdisp_t *vbarray_constr;
- jsdisp_t *map_prototype;
- jsdisp_t *set_prototype;
+ union {
+ struct {
+ jsdisp_t *global;
+ jsdisp_t *function_constr;
+ jsdisp_t *array_constr;
+ jsdisp_t *bool_constr;
+ jsdisp_t *date_constr;
+ jsdisp_t *enumerator_constr;
+ jsdisp_t *error_constr;
+ jsdisp_t *eval_error_constr;
+ jsdisp_t *range_error_constr;
+ jsdisp_t *reference_error_constr;
+ jsdisp_t *regexp_error_constr;
+ jsdisp_t *syntax_error_constr;
+ jsdisp_t *type_error_constr;
+ jsdisp_t *uri_error_constr;
+ jsdisp_t *number_constr;
+ jsdisp_t *object_constr;
+ jsdisp_t *object_prototype;
+ jsdisp_t *regexp_constr;
+ jsdisp_t *string_constr;
+ jsdisp_t *vbarray_constr;
+ jsdisp_t *map_prototype;
+ jsdisp_t *set_prototype;
+ };
+ jsdisp_t *global_objects[22];
+ };
};
+C_ASSERT(RTL_SIZEOF_THROUGH_FIELD(script_ctx_t, set_prototype) == RTL_SIZEOF_THROUGH_FIELD(script_ctx_t, global_objects));
void script_release(script_ctx_t*) DECLSPEC_HIDDEN;
diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c
index f7ad1fe..ec054f0 100644
--- a/dlls/jscript/tests/run.c
+++ b/dlls/jscript/tests/run.c
@@ -3293,7 +3293,6 @@ static void test_invokeex(void)
str = SysAllocString(L"call");
hres = IDispatchEx_GetDispID(dispex, str, 0, &func_id);
SysFreeString(str);
- todo_wine
ok(hres == E_UNEXPECTED, "GetDispID failed: %08lx\n", hres);
IDispatchEx_Release(dispex);
--
2.34.1
June 2, 2022
[PATCH v4 4/6] jscript: Forward actual error in to_primitive if it's not just missing prop.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
Needed for next patch.
dlls/jscript/jsutils.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c
index 3251abf..96e4262 100644
--- a/dlls/jscript/jsutils.c
+++ b/dlls/jscript/jsutils.c
@@ -422,6 +422,9 @@ HRESULT to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *ret, hint_t hint)
}else {
IDispatch_Release(get_object(prim));
}
+ }else if(hres != DISP_E_UNKNOWNNAME) {
+ jsdisp_release(jsdisp);
+ return hres;
}
hres = jsdisp_get_id(jsdisp, hint == HINT_STRING ? L"valueOf" : L"toString", 0, &id);
@@ -438,6 +441,9 @@ HRESULT to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *ret, hint_t hint)
}else {
IDispatch_Release(get_object(prim));
}
+ }else if(hres != DISP_E_UNKNOWNNAME) {
+ jsdisp_release(jsdisp);
+ return hres;
}
jsdisp_release(jsdisp);
--
2.34.1
June 2, 2022
[PATCH v4 3/6] jscript: Don't execute any functions if script state does not allow it.
by Gabriel Ivăncescu
Instead of only interpreted functions. Property retrievals or setters are
allowed though, as long as they are not accessors.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/dispex.c | 3 ++
dlls/jscript/function.c | 10 ++--
dlls/jscript/tests/run.c | 111 ++++++++++++++++++++++++++++++++++++---
3 files changed, 111 insertions(+), 13 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index df829b7..298f7e1 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -1971,6 +1971,9 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsig
return JS_E_FUNCTION_EXPECTED;
}
+ if(jsfunc->ctx->state == SCRIPTSTATE_UNINITIALIZED || jsfunc->ctx->state == SCRIPTSTATE_CLOSED)
+ return E_UNEXPECTED;
+
flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
hres = jsfunc->builtin_info->call(jsfunc->ctx, jsthis ? jsval_disp(jsthis) : jsval_null(), flags, argc, argv, r);
}
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c
index 18465e5..984eebf 100644
--- a/dlls/jscript/function.c
+++ b/dlls/jscript/function.c
@@ -257,6 +257,11 @@ HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsi
assert(is_class(func_this, JSCLASS_FUNCTION));
function = function_from_jsdisp(func_this);
+ if(function->dispex.ctx->state == SCRIPTSTATE_UNINITIALIZED || function->dispex.ctx->state == SCRIPTSTATE_CLOSED) {
+ WARN("Script engine state does not allow running code.\n");
+ return E_UNEXPECTED;
+ }
+
if(jsthis)
vthis = jsval_disp(jsthis);
else
@@ -725,11 +730,6 @@ static HRESULT InterpretedFunction_call(script_ctx_t *ctx, FunctionInstance *fun
TRACE("%p\n", function);
- if(ctx->state == SCRIPTSTATE_UNINITIALIZED || ctx->state == SCRIPTSTATE_CLOSED) {
- WARN("Script engine state does not allow running code.\n");
- return E_UNEXPECTED;
- }
-
if(flags & DISPATCH_CONSTRUCT) {
hres = create_object(ctx, &function->function.dispex, &new_obj);
if(FAILED(hres))
diff --git a/dlls/jscript/tests/run.c b/dlls/jscript/tests/run.c
index 94dc2e1..f7ad1fe 100644
--- a/dlls/jscript/tests/run.c
+++ b/dlls/jscript/tests/run.c
@@ -2914,13 +2914,20 @@ static void test_default_value(void)
V_VT(&v) = VT_EMPTY;
hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL);
- ok(hres == S_OK || broken(hres == 0x8000ffff), "Invoke failed: %08lx\n", hres);
- if(hres == S_OK)
- {
- ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v));
- }
+ ok(hres == E_UNEXPECTED, "Invoke failed: %08lx\n", hres);
+
+ hres = parse_script_expr(L"new Date()", &v, &script);
+ ok(hres == S_OK, "parse_script_expr failed: %08lx\n", hres);
+ ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
+ disp = V_DISPATCH(&v);
+
+ V_VT(&v) = VT_EMPTY;
+ hres = IDispatch_Invoke(disp, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL);
+ ok(hres == S_OK, "Invoke failed: %08lx\n", hres);
+ ok(V_VT(&v) == VT_BSTR, "V_VT(v) = %d\n", V_VT(&v));
VariantClear(&v);
IDispatch_Release(disp);
+ close_script(script);
hres = parse_script_expr(L"var arr = [5]; arr.toString = function() {return \"foo\";}; arr.valueOf = function() {return 42;}; arr", &v, &script);
ok(hres == S_OK, "parse_script_expr failed: %08lx\n", hres);
@@ -3149,15 +3156,15 @@ static void test_script_exprs(void)
static void test_invokeex(void)
{
- DISPID func_id, prop_id;
- DISPPARAMS dp = {NULL};
+ DISPPARAMS dp = {NULL}, dp_max = {NULL};
+ DISPID func_id, max_id, prop_id;
IActiveScript *script;
IDispatchEx *dispex;
VARIANT v, arg;
BSTR str;
HRESULT hres;
- hres = parse_script_expr(L"var o = {func: function() {return 3;}, prop: 6}; o", &v, &script);
+ hres = parse_script_expr(L"var o = {func: function() {return 3;}, max: Math.max, prop: 6}; o", &v, &script);
ok(hres == S_OK, "parse_script_expr failed: %08lx\n", hres);
ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
@@ -3170,16 +3177,31 @@ static void test_invokeex(void)
SysFreeString(str);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
+ str = SysAllocString(L"max");
+ hres = IDispatchEx_GetDispID(dispex, str, 0, &max_id);
+ SysFreeString(str);
+ ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
+
str = SysAllocString(L"prop");
hres = IDispatchEx_GetDispID(dispex, str, 0, &prop_id);
SysFreeString(str);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
+ dp_max.rgvarg = &arg;
+ dp_max.cArgs = 1;
+ V_VT(&arg) = VT_I4;
+ V_I4(&arg) = 42;
+
hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_METHOD, &dp, &v, NULL, NULL);
ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v));
ok(V_I4(&v) == 3, "V_I4(v) = %ld\n", V_I4(&v));
+ hres = IDispatchEx_InvokeEx(dispex, max_id, 0, DISPATCH_METHOD, &dp_max, &v, NULL, NULL);
+ ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
+ ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v));
+ ok(V_I4(&v) == 42, "V_I4(v) = %ld\n", V_I4(&v));
+
hres = IDispatchEx_InvokeEx(dispex, prop_id, 0, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL);
ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v));
@@ -3193,9 +3215,23 @@ static void test_invokeex(void)
SysFreeString(str);
ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
+ V_VT(&v) = VT_EMPTY;
hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_METHOD, &dp, &v, NULL, NULL);
ok(hres == E_UNEXPECTED || broken(hres == 0x800a1393), "InvokeEx failed: %08lx\n", hres);
+ V_VT(&v) = VT_EMPTY;
+ hres = IDispatchEx_InvokeEx(dispex, max_id, 0, DISPATCH_METHOD, &dp_max, &v, NULL, NULL);
+ ok(hres == E_UNEXPECTED || broken(hres == 0x800a1393), "InvokeEx failed: %08lx\n", hres);
+
+ V_VT(&v) = VT_EMPTY;
+ hres = IDispatchEx_InvokeEx(dispex, prop_id, 0, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL);
+ ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
+ ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v));
+ ok(V_I4(&v) == 6, "V_I4(v) = %ld\n", V_I4(&v));
+
+ IActiveScript_Close(script);
+
+ V_VT(&v) = VT_EMPTY;
hres = IDispatchEx_InvokeEx(dispex, prop_id, 0, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL);
ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v));
@@ -3204,6 +3240,65 @@ static void test_invokeex(void)
IDispatchEx_Release(dispex);
IActiveScript_Release(script);
+ hres = parse_script_expr(L"Math.max", &v, &script);
+ ok(hres == S_OK, "parse_script_expr failed: %08lx\n", hres);
+ ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
+
+ hres = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IDispatchEx, (void**)&dispex);
+ ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres);
+ VariantClear(&v);
+
+ str = SysAllocString(L"call");
+ hres = IDispatchEx_GetDispID(dispex, str, 0, &func_id);
+ SysFreeString(str);
+ ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
+
+ hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED);
+ ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08lx\n", hres);
+
+ str = SysAllocString(L"call");
+ hres = IDispatchEx_GetDispID(dispex, str, 0, &func_id);
+ SysFreeString(str);
+ ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
+
+ str = SysAllocString(L"length");
+ hres = IDispatchEx_GetDispID(dispex, str, 0, &prop_id);
+ SysFreeString(str);
+ ok(hres == S_OK, "GetDispID failed: %08lx\n", hres);
+
+ hres = IDispatchEx_InvokeEx(dispex, func_id, 0, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL);
+ ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
+ ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
+ VariantClear(&v);
+
+ hres = IDispatchEx_InvokeEx(dispex, prop_id, 0, DISPATCH_PROPERTYGET, &dp, &v, NULL, NULL);
+ ok(hres == S_OK, "InvokeEx failed: %08lx\n", hres);
+ ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v));
+ ok(V_I4(&v) == 2, "V_I4(v) = %ld\n", V_I4(&v));
+
+ IDispatchEx_Release(dispex);
+ IActiveScript_Release(script);
+
+ hres = parse_script_expr(L"Math.max", &v, &script);
+ ok(hres == S_OK, "parse_script_expr failed: %08lx\n", hres);
+ ok(V_VT(&v) == VT_DISPATCH, "V_VT(v) = %d\n", V_VT(&v));
+
+ hres = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IDispatchEx, (void**)&dispex);
+ ok(hres == S_OK, "Could not get IDispatchEx iface: %08lx\n", hres);
+ VariantClear(&v);
+
+ hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED);
+ ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08lx\n", hres);
+
+ str = SysAllocString(L"call");
+ hres = IDispatchEx_GetDispID(dispex, str, 0, &func_id);
+ SysFreeString(str);
+ todo_wine
+ ok(hres == E_UNEXPECTED, "GetDispID failed: %08lx\n", hres);
+
+ IDispatchEx_Release(dispex);
+ IActiveScript_Release(script);
+
/* test InvokeEx following prototype chain of builtin object (PROP_PROTREF) */
hres = parse_script_expr(L"o = new Array(); o.push(\"foo\"); o", &v, &script);
ok(hres == S_OK, "parse_script_expr failed: %08lx\n", hres);
--
2.34.1
June 2, 2022
[PATCH v4 2/6] jscript: Setup builtin function when the dispid is retrieved.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/jscript/dispex.c | 67 ++++++++++++++---------------------------
dlls/jscript/function.c | 3 ++
2 files changed, 25 insertions(+), 45 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index 468a0dd..df829b7 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -242,6 +242,7 @@ static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name,
const builtin_prop_t *builtin;
unsigned bucket, pos, prev = ~0;
dispex_prop_t *prop;
+ HRESULT hres;
bucket = get_props_idx(This, hash);
pos = This->props[bucket].bucket_head;
@@ -264,9 +265,24 @@ static HRESULT find_prop_name(jsdisp_t *This, unsigned hash, const WCHAR *name,
builtin = find_builtin_prop(This, name);
if(builtin) {
unsigned flags = builtin->flags;
- if(flags & PROPF_METHOD)
- flags |= PROPF_WRITABLE | PROPF_CONFIGURABLE;
- else if(builtin->setter)
+ if(flags & PROPF_METHOD) {
+ jsdisp_t *obj;
+
+ hres = create_builtin_function(This->ctx, builtin->invoke, builtin->name, NULL, flags, NULL, &obj);
+ if(FAILED(hres))
+ return hres;
+
+ prop = alloc_prop(This, name, PROP_JSVAL, (flags & PROPF_ALL) | PROPF_WRITABLE | PROPF_CONFIGURABLE);
+ if(!prop) {
+ jsdisp_release(obj);
+ return E_OUTOFMEMORY;
+ }
+
+ prop->type = PROP_JSVAL;
+ prop->u.val = jsval_obj(obj);
+ *ret = prop;
+ return S_OK;
+ }else if(builtin->setter)
flags |= PROPF_WRITABLE;
flags &= PROPF_ENUMERABLE | PROPF_WRITABLE | PROPF_CONFIGURABLE;
prop = alloc_prop(This, name, PROP_BUILTIN, flags);
@@ -431,23 +447,7 @@ static HRESULT prop_get(jsdisp_t *This, dispex_prop_t *prop, jsval_t *r)
switch(prop->type) {
case PROP_BUILTIN:
- if(prop->u.p->getter) {
- hres = prop->u.p->getter(This->ctx, This, r);
- }else {
- jsdisp_t *obj;
-
- assert(prop->u.p->invoke != NULL);
- hres = create_builtin_function(This->ctx, prop->u.p->invoke, prop->u.p->name, NULL,
- prop->u.p->flags, NULL, &obj);
- if(FAILED(hres))
- break;
-
- prop->type = PROP_JSVAL;
- prop->u.val = jsval_obj(obj);
-
- jsdisp_addref(obj);
- *r = jsval_obj(obj);
- }
+ hres = prop->u.p->getter(This->ctx, This, r);
break;
case PROP_JSVAL:
hres = jsval_copy(prop->u.val, r);
@@ -497,12 +497,6 @@ static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val)
switch(prop->type) {
case PROP_BUILTIN:
- if(prop->u.p->invoke) {
- prop->type = PROP_JSVAL;
- prop->flags = PROPF_CONFIGURABLE | PROPF_WRITABLE;
- prop->u.val = jsval_undefined();
- break;
- }
if(!prop->u.p->setter) {
TRACE("getter with no setter\n");
return S_OK;
@@ -557,25 +551,8 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t
HRESULT hres;
switch(prop->type) {
- case PROP_BUILTIN: {
- jsval_t vthis;
-
- if(!prop->u.p->invoke)
- return JS_E_FUNCTION_EXPECTED;
-
- if(flags == DISPATCH_CONSTRUCT && (prop->flags & PROPF_METHOD)) {
- WARN("%s is not a constructor\n", debugstr_w(prop->name));
- return E_INVALIDARG;
- }
-
- if(This->builtin_info->class != JSCLASS_FUNCTION && prop->u.p->invoke != JSGlobal_eval)
- flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
- if(jsthis)
- vthis = jsval_disp(jsthis);
- else
- vthis = jsval_obj(This);
- return prop->u.p->invoke(This->ctx, vthis, flags, argc, argv, r);
- }
+ case PROP_BUILTIN:
+ return JS_E_FUNCTION_EXPECTED;
case PROP_PROTREF:
return invoke_prop_func(This->prototype, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface,
This->prototype->props+prop->u.ref, flags, argc, argv, r, caller);
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c
index 638d176..18465e5 100644
--- a/dlls/jscript/function.c
+++ b/dlls/jscript/function.c
@@ -664,6 +664,9 @@ HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc,
NativeFunction *function;
HRESULT hres;
+ if(!ctx->function_constr)
+ return E_UNEXPECTED;
+
hres = create_function(ctx, builtin_info, &NativeFunctionVtbl, sizeof(NativeFunction), flags, FALSE, NULL, (void**)&function);
if(FAILED(hres))
return hres;
--
2.34.1
June 2, 2022
[PATCH v4 1/6] jscript: Don't allow starting script using state from uninitialized.
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
v4: Fix error on last patch.
dlls/jscript/jscript.c | 2 +-
dlls/jscript/tests/jscript.c | 6 ++++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c
index 8cf141d..d6028e6 100644
--- a/dlls/jscript/jscript.c
+++ b/dlls/jscript/jscript.c
@@ -824,7 +824,7 @@ static HRESULT WINAPI JScript_SetScriptState(IActiveScript *iface, SCRIPTSTATE s
switch(ss) {
case SCRIPTSTATE_STARTED:
case SCRIPTSTATE_CONNECTED: /* FIXME */
- if(This->ctx->state == SCRIPTSTATE_CLOSED)
+ if(This->ctx->state == SCRIPTSTATE_UNINITIALIZED || This->ctx->state == SCRIPTSTATE_CLOSED)
return E_UNEXPECTED;
exec_queued_code(This);
diff --git a/dlls/jscript/tests/jscript.c b/dlls/jscript/tests/jscript.c
index 8c985e5..8723541 100644
--- a/dlls/jscript/tests/jscript.c
+++ b/dlls/jscript/tests/jscript.c
@@ -863,6 +863,12 @@ static void test_jscript_uninitializing(void)
hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_UNINITIALIZED);
ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_UNINITIALIZED) failed: %08lx\n", hres);
+ hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_STARTED);
+ ok(hres == E_UNEXPECTED, "SetScriptState(SCRIPTSTATE_STARTED) returned: %08lx\n", hres);
+
+ hres = IActiveScript_SetScriptState(script, SCRIPTSTATE_CONNECTED);
+ ok(hres == E_UNEXPECTED, "SetScriptState(SCRIPTSTATE_CONNECTED) returned: %08lx\n", hres);
+
SET_EXPECT(GetLCID);
SET_EXPECT(OnStateChange_INITIALIZED);
hres = IActiveScript_SetScriptSite(script, &ActiveScriptSite);
--
2.34.1
June 2, 2022