Wine-Devel
Threads by month
- ----- 2026 -----
- 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
- 4 participants
- 84544 discussions
From: shaoming <shaoming(a)uniontech.com>
Signed-off-by: shaoming <shaoming(a)uniontech.com>
---
dlls/shell32/shlfileop.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/dlls/shell32/shlfileop.c b/dlls/shell32/shlfileop.c
index 17a8e7046c7..aa69c7a3232 100644
--- a/dlls/shell32/shlfileop.c
+++ b/dlls/shell32/shlfileop.c
@@ -1519,6 +1519,14 @@ int WINAPI SHFileOperationW(LPSHFILEOPSTRUCTW lpFileOp)
ZeroMemory(&flFrom, sizeof(FILE_LIST));
ZeroMemory(&flTo, sizeof(FILE_LIST));
+ //windows look likes select first path when lpFileOp->pTo have more then one paths
+ if(lpFileOp->wFunc == FO_RENAME)
+ {
+ LPWSTR lpRefTo = lpFileOp->pTo;
+ while(*lpRefTo++);
+ if(*lpRefTo) *lpRefTo = '\0';
+ }
+
if ((ret = parse_file_list(&flFrom, lpFileOp->pFrom)))
return ret;
--
2.20.1
1
0
[PATCH v2 01/12] wintab32: Standardize location of WTPACKET definition.
by Elaine Lefler March 25, 2022
by Elaine Lefler March 25, 2022
March 25, 2022
Signed-off-by: Elaine Lefler <elaineclefler(a)gmail.com>
---
v2: Splitting into smaller patches as per feedback.
This structure was being defined redundantly in multiple places. It has
been moved to a public header where everyone can access it.
pktdef.h, which was never used at all, has been removed.
---
dlls/winex11.drv/wintab.c | 17 ---
dlls/wintab32/wintab_internal.h | 17 ---
include/Makefile.in | 1 -
include/pktdef.h | 248 --------------------------------
include/wintab.h | 19 ++-
5 files changed, 17 insertions(+), 285 deletions(-)
delete mode 100644 include/pktdef.h
diff --git a/dlls/winex11.drv/wintab.c b/dlls/winex11.drv/wintab.c
index 331601c3325..ef9bbc6be45 100644
--- a/dlls/winex11.drv/wintab.c
+++ b/dlls/winex11.drv/wintab.c
@@ -233,23 +233,6 @@ typedef struct tagWTI_DEVICES_INFO
* linux wacom lists all the known values and this isn't one of them */
#define CSR_TYPE_OTHER 0x000
-typedef struct tagWTPACKET {
- HCTX pkContext;
- UINT pkStatus;
- LONG pkTime;
- WTPKT pkChanged;
- UINT pkSerialNumber;
- UINT pkCursor;
- DWORD pkButtons;
- DWORD pkX;
- DWORD pkY;
- DWORD pkZ;
- UINT pkNormalPressure;
- UINT pkTangentPressure;
- ORIENTATION pkOrientation;
- ROTATION pkRotation; /* 1.1 */
-} WTPACKET, *LPWTPACKET;
-
#ifdef SONAME_LIBXI
diff --git a/dlls/wintab32/wintab_internal.h b/dlls/wintab32/wintab_internal.h
index 18c64bfe700..3b31d021f66 100644
--- a/dlls/wintab32/wintab_internal.h
+++ b/dlls/wintab32/wintab_internal.h
@@ -116,23 +116,6 @@ typedef struct tagWTI_EXTENSIONS_INFO
*/
} WTI_EXTENSIONS_INFO, *LPWTI_EXTENSIONS_INFO;
-typedef struct tagWTPACKET {
- HCTX pkContext;
- UINT pkStatus;
- LONG pkTime;
- WTPKT pkChanged;
- UINT pkSerialNumber;
- UINT pkCursor;
- DWORD pkButtons;
- DWORD pkX;
- DWORD pkY;
- DWORD pkZ;
- UINT pkNormalPressure;
- UINT pkTangentPressure;
- ORIENTATION pkOrientation;
- ROTATION pkRotation; /* 1.1 */
-} WTPACKET, *LPWTPACKET;
-
typedef struct tagOPENCONTEXT
{
HCTX handle;
diff --git a/include/Makefile.in b/include/Makefile.in
index 9578c557af7..b9d2f8416fa 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -590,7 +590,6 @@ SOURCES = \
perflib.h \
perhist.idl \
physicalmonitorenumerationapi.h \
- pktdef.h \
poppack.h \
powrprof.h \
prntvpt.h \
diff --git a/include/pktdef.h b/include/pktdef.h
deleted file mode 100644
index a1622062658..00000000000
--- a/include/pktdef.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (C) 1991-1998 by LCS/Telegraphics
- * Copyright (C) 2002 Patrik Stridvall
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#ifndef __WINE_PKTDEF_H
-#define __WINE_PKTDEF_H
-
-/***********************************************************************
- * How to use pktdef.h:
- *
- * 1. Include wintab.h
- * 2. if using just one packet format:
- * a. Define PACKETDATA and PACKETMODE as or'ed combinations of WTPKT bits
- * (use the PK_* identifiers).
- * b. Include pktdef.h.
- * c. The generated structure typedef will be called PACKET. Use PACKETDATA
- * and PACKETMODE to fill in the LOGCONTEXT structure.
- * 3. If using multiple packet formats, for each one:
- * a. Define PACKETNAME. Its text value will be a prefix for this packet's
- * parameters and names.
- * b. Define <PACKETNAME>PACKETDATA and <PACKETNAME>PACKETMODE similar to
- * 2.a. above.
- * c. Include pktdef.h.
- * d. The generated structure typedef will be called
- * <PACKETNAME>PACKET. Compare with 2.c. above and example #2 below.
- * 4. If using extension packet data, do the following additional steps
- * for each extension:
- * a. Before including pktdef.h, define <PACKETNAME>PACKET<EXTENSION>
- * as either PKEXT_ABSOLUTE or PKEXT_RELATIVE.
- * b. The generated structure typedef will contain a field for the
- * extension data.
- * c. Scan the WTI_EXTENSION categories to find the extension's
- * packet mask bit.
- * d. OR the packet mask bit with <PACKETNAME>PACKETDATA and use the
- * result in the lcPktData field of the LOGCONTEXT structure.
- * e. If <PACKETNAME>PACKET<EXTENSION> was PKEXT_RELATIVE, OR the
- * packet mask bit with <PACKETNAME>PACKETMODE and use the result
- * in the lcPktMode field of the LOGCONTEXT structure.
- *
- *
- * Example #1. -- single packet format
- *
- * #include <wintab.h>
- * #define PACKETDATA PK_X | PK_Y | PK_BUTTONS /@ x, y, buttons @/
- * #define PACKETMODE PK_BUTTONS /@ buttons relative mode @/
- * #include <pktdef.h>
- * ...
- * lc.lcPktData = PACKETDATA;
- * lc.lcPktMode = PACKETMODE;
- *
- * Example #2. -- multiple formats
- *
- * #include <wintab.h>
- * #define PACKETNAME MOE
- * #define MOEPACKETDATA PK_X | PK_Y | PK_BUTTONS /@ x, y, buttons @/
- * #define MOEPACKETMODE PK_BUTTONS /@ buttons relative mode @/
- * #include <pktdef.h>
- * #define PACKETNAME LARRY
- * #define LARRYPACKETDATA PK_Y | PK_Z | PK_BUTTONS /@ y, z, buttons @/
- * #define LARRYPACKETMODE PK_BUTTONS /@ buttons relative mode @/
- * #include <pktdef.h>
- * #define PACKETNAME CURLY
- * #define CURLYPACKETDATA PK_X | PK_Z | PK_BUTTONS /@ x, z, buttons @/
- * #define CURLYPACKETMODE PK_BUTTONS /@ buttons relative mode @/
- * #include <pktdef.h>
- * ...
- * lcMOE.lcPktData = MOEPACKETDATA;
- * lcMOE.lcPktMode = MOEPACKETMODE;
- * ...
- * lcLARRY.lcPktData = LARRYPACKETDATA;
- * lcLARRY.lcPktMode = LARRYPACKETMODE;
- * ...
- * lcCURLY.lcPktData = CURLYPACKETDATA;
- * lcCURLY.lcPktMode = CURLYPACKETMODE;
- *
- * Example #3. -- extension packet data "XFOO".
- *
- * #include <wintab.h>
- * #define PACKETDATA PK_X | PK_Y | PK_BUTTONS /@ x, y, buttons @/
- * #define PACKETMODE PK_BUTTONS /@ buttons relative mode @/
- * #define PACKETXFOO PKEXT_ABSOLUTE /@ XFOO absolute mode @/
- * #include <pktdef.h>
- * ...
- * UINT ScanExts(UINT wTag)
- * {
- * UINT i;
- * UINT wScanTag;
- *
- * /@ scan for wTag's info category. @/
- * for (i = 0; WTInfo(WTI_EXTENSIONS + i, EXT_TAG, &wScanTag); i++) {
- * if (wTag == wScanTag) {
- * /@ return category offset from WTI_EXTENSIONS. @/
- * return i;
- * }
- * }
- * /@ return error code. @/
- * return 0xFFFF;
- * }
- * ...
- * lc.lcPktData = PACKETDATA;
- * lc.lcPktMode = PACKETMODE;
- * #ifdef PACKETXFOO
- * categoryXFOO = ScanExts(WTX_XFOO);
- * WTInfo(WTI_EXTENSIONS + categoryXFOO, EXT_MASK, &maskXFOO);
- * lc.lcPktData |= maskXFOO;
- * #if PACKETXFOO == PKEXT_RELATIVE
- * lc.lcPktMode |= maskXFOO;
- * #endif
- * #endif
- * WTOpen(hWnd, &lc, TRUE);
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* defined(__cplusplus) */
-
-#ifndef PACKETNAME
-/* if no packet name prefix */
-# define __PFX(x) x
-# define __IFX(x,y) x ## y
-#else
-/* add prefixes and infixes to packet format names */
-# define __PFX(x) __PFX2(PACKETNAME,x)
-# define __PFX2(p,x) __PFX3(p,x)
-# define __PFX3(p,x) p ## x
-# define __IFX(x,y) __IFX2(x,PACKETNAME,y)
-# define __IFX2(x,i,y) __IFX3(x,i,y)
-# define __IFX3(x,i,y) x ## i ## y
-#endif
-
-#define __SFX2(x,s) __SFX3(x,s)
-#define __SFX3(x,s) x ## s
-
-#define __TAG __IFX(tag,PACKET)
-#define __TYPES \
- __PFX(PACKET), * __IFX(P,PACKET), \
- * __IFX(NP,PACKET), * __IFX(LP,PACKET)
-
-#define __DATA (__PFX(PACKETDATA))
-#define __MODE (__PFX(PACKETMODE))
-#define __EXT(x) __SFX2(__PFX(PACKET),x)
-
-typedef struct __TAG {
-#if (__DATA & PK_CONTEXT)
- HCTX pkContext;
-#endif
-#if (__DATA & PK_STATUS)
- UINT pkStatus;
-#endif
-#if (__DATA & PK_TIME)
- DWORD pkTime;
-#endif
-#if (__DATA & PK_CHANGED)
- WTPKT pkChanged;
-#endif
-#if (__DATA & PK_SERIAL_NUMBER)
- UINT pkSerialNumber;
-#endif
-#if (__DATA & PK_CURSOR)
- UINT pkCursor;
-#endif
-#if (__DATA & PK_BUTTONS)
- DWORD pkButtons;
-#endif
-#if (__DATA & PK_X)
- LONG pkX;
-#endif
-#if (__DATA & PK_Y)
- LONG pkY;
-#endif
-#if (__DATA & PK_Z)
- LONG pkZ;
-#endif
-#if (__DATA & PK_NORMAL_PRESSURE)
-# if (__MODE & PK_NORMAL_PRESSURE)
- /* relative */
- int pkNormalPressure;
-# else
- /* absolute */
- UINT pkNormalPressure;
-# endif
-#endif
-#if (__DATA & PK_TANGENT_PRESSURE)
-# if (__MODE & PK_TANGENT_PRESSURE)
- /* relative */
- int pkTangentPressure;
-# else
- /* absolute */
- UINT pkTangentPressure;
-# endif
-#endif
-#if (__DATA & PK_ORIENTATION)
- ORIENTATION pkOrientation;
-#endif
-#if (__DATA & PK_ROTATION)
- ROTATION pkRotation; /* 1.1 */
-#endif
-
-#ifndef NOWTEXTENSIONS
- /* extensions begin here. */
-
-#if (__EXT(FKEYS) == PKEXT_RELATIVE) || (__EXT(FKEYS) == PKEXT_ABSOLUTE)
- UINT pkFKeys;
-#endif
-#if (__EXT(TILT) == PKEXT_RELATIVE) || (__EXT(TILT) == PKEXT_ABSOLUTE)
- TILT pkTilt;
-#endif
-
-#endif
-
-} __TYPES;
-
-#undef PACKETNAME
-#undef __TAG
-#undef __TAG2
-#undef __TYPES
-#undef __TYPES2
-#undef __DATA
-#undef __MODE
-#undef __PFX
-#undef __PFX2
-#undef __PFX3
-#undef __IFX
-#undef __IFX2
-#undef __IFX3
-#undef __SFX2
-#undef __SFX3
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* defined(__cplusplus) */
-
-#endif /* defined(__WINE_PKTDEF_H */
diff --git a/include/wintab.h b/include/wintab.h
index d10371b0217..9f607bbe7ef 100644
--- a/include/wintab.h
+++ b/include/wintab.h
@@ -462,8 +462,6 @@ DECL_WINELIB_TYPE_AW(LPLOGCONTEXT)
* EVENT DATA DEFS
*/
-/* For packet structure definition, see pktdef.h */
-
/* packet status values */
#define TPS_PROXIMITY 0x0001
#define TPS_QUEUE_ERR 0x0002
@@ -493,6 +491,23 @@ typedef struct tagROTATION { /* 1.1 */
#define TBN_UP 1
#define TBN_DOWN 2
+typedef struct tagWTPACKET {
+ HCTX pkContext;
+ UINT pkStatus;
+ LONG pkTime;
+ WTPKT pkChanged;
+ UINT pkSerialNumber;
+ UINT pkCursor;
+ DWORD pkButtons;
+ DWORD pkX;
+ DWORD pkY;
+ DWORD pkZ;
+ UINT pkNormalPressure;
+ UINT pkTangentPressure;
+ ORIENTATION pkOrientation;
+ ROTATION pkRotation; /* 1.1 */
+} WTPACKET, *LPWTPACKET;
+
/***********************************************************************
* DEVICE CONFIG CONSTANTS
*/
--
2.32.0 (Apple Git-132)
1
11
[PATCH v4 resend 1/2] ntdll/tests: Add more tests for \Device\NamedPipe\ root directory.
by Jinoh Kang March 24, 2022
by Jinoh Kang March 24, 2022
March 24, 2022
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
Notes:
v2 -> v3: move some tests from om.c to pipe.c
v3 -> v4: fix and simplify STATUS_PENDING testing
dlls/ntdll/tests/om.c | 9 +++++
dlls/ntdll/tests/pipe.c | 90 ++++++++++++++++++++++++++++++++++++++++-
2 files changed, 98 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c
index 946f54523b3..0f9b97a8a02 100644
--- a/dlls/ntdll/tests/om.c
+++ b/dlls/ntdll/tests/om.c
@@ -1872,6 +1872,15 @@ static void test_query_object(void)
pNtClose( handle );
+ handle = CreateFileA( "\\\\.\\pipe\\", 0, 0, NULL, OPEN_EXISTING, 0, 0 );
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError() );
+
+ test_object_name( handle, L"\\Device\\NamedPipe\\", TRUE );
+ test_object_type( handle, L"File" );
+ test_file_info( handle );
+
+ pNtClose( handle );
+
RtlInitUnicodeString( &path, L"\\REGISTRY\\Machine" );
status = pNtCreateKey( &handle, KEY_READ, &attr, 0, 0, 0, 0 );
ok( status == STATUS_SUCCESS, "NtCreateKey failed status %lx\n", status );
diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c
index 38d1d92b4a9..67be9522c66 100644
--- a/dlls/ntdll/tests/pipe.c
+++ b/dlls/ntdll/tests/pipe.c
@@ -52,6 +52,13 @@ typedef struct {
ULONG NamedPipeEnd;
} FILE_PIPE_LOCAL_INFORMATION;
+typedef struct _FILE_PIPE_WAIT_FOR_BUFFER {
+ LARGE_INTEGER Timeout;
+ ULONG NameLength;
+ BOOLEAN TimeoutSpecified;
+ WCHAR Name[1];
+} FILE_PIPE_WAIT_FOR_BUFFER, *PFILE_PIPE_WAIT_FOR_BUFFER;
+
#ifndef FILE_SYNCHRONOUS_IO_ALERT
#define FILE_SYNCHRONOUS_IO_ALERT 0x10
#endif
@@ -63,6 +70,10 @@ typedef struct {
#ifndef FSCTL_PIPE_LISTEN
#define FSCTL_PIPE_LISTEN CTL_CODE(FILE_DEVICE_NAMED_PIPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif
+
+#ifndef FSCTL_PIPE_WAIT
+#define FSCTL_PIPE_WAIT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#endif
#endif
static NTSTATUS (WINAPI *pNtFsControlFile) (HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, PVOID apc_context, PIO_STATUS_BLOCK io, ULONG code, PVOID in_buffer, ULONG in_size, PVOID out_buffer, ULONG out_size);
@@ -178,6 +189,48 @@ static NTSTATUS listen_pipe(HANDLE hPipe, HANDLE hEvent, PIO_STATUS_BLOCK iosb,
return pNtFsControlFile(hPipe, hEvent, use_apc ? &ioapc: NULL, use_apc ? &dummy: NULL, iosb, FSCTL_PIPE_LISTEN, 0, 0, 0, 0);
}
+static NTSTATUS wait_pipe(HANDLE handle, PUNICODE_STRING name, const LARGE_INTEGER* timeout)
+{
+ HANDLE event;
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES attr;
+ IO_STATUS_BLOCK iosb;
+ FILE_PIPE_WAIT_FOR_BUFFER *pipe_wait;
+ ULONG pipe_wait_size;
+
+ pipe_wait_size = offsetof(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) + name->Length;
+ pipe_wait = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pipe_wait_size);
+ if (!pipe_wait) return STATUS_NO_MEMORY;
+
+ pipe_wait->TimeoutSpecified = !!timeout;
+ pipe_wait->NameLength = name->Length;
+ if (timeout) pipe_wait->Timeout = *timeout;
+ memcpy(pipe_wait->Name, name->Buffer, name->Length);
+
+ InitializeObjectAttributes(&attr, NULL, 0, 0, NULL);
+ status = NtCreateEvent(&event, GENERIC_ALL, &attr, NotificationEvent, FALSE);
+ if (status != STATUS_SUCCESS)
+ {
+ ok(0, "NtCreateEvent failure: %08x\n", status);
+ HeapFree(GetProcessHeap(), 0, pipe_wait);
+ return status;
+ }
+
+ memset(&iosb, 0, sizeof(iosb));
+ iosb.Status = STATUS_PENDING;
+ status = pNtFsControlFile(handle, event, NULL, NULL, &iosb, FSCTL_PIPE_WAIT,
+ pipe_wait, pipe_wait_size, NULL, 0);
+ if (status == STATUS_PENDING)
+ {
+ WaitForSingleObject(event, INFINITE);
+ status = iosb.Status;
+ }
+
+ NtClose(event);
+ HeapFree(GetProcessHeap(), 0, pipe_wait);
+ return status;
+}
+
static void test_create_invalid(void)
{
IO_STATUS_BLOCK iosb;
@@ -2421,6 +2474,7 @@ static void test_security_info(void)
static void test_empty_name(void)
{
+ static const LARGE_INTEGER zero_timeout = {{ 0 }};
HANDLE hdirectory, hpipe, hpipe2, hwrite, hwrite2, handle;
OBJECT_TYPE_INFORMATION *type_info;
OBJECT_NAME_INFORMATION *name_info;
@@ -2451,6 +2505,10 @@ static void test_empty_name(void)
FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0 );
ok(!status, "Got unexpected status %#lx.\n", status);
+ pRtlInitUnicodeString(&name, L"nonexistent_pipe");
+ status = wait_pipe(hdirectory, &name, &zero_timeout);
+ todo_wine ok(status == STATUS_ILLEGAL_FUNCTION, "unexpected status for FSCTL_PIPE_WAIT on \\Device\\NamedPipe: %08x\n", status);
+
name.Buffer = NULL;
name.Length = 0;
name.MaximumLength = 0;
@@ -2463,6 +2521,17 @@ static void test_empty_name(void)
todo_wine ok(status == STATUS_OBJECT_NAME_INVALID, "Got unexpected status %#lx.\n", status);
if (!status)
CloseHandle(hpipe);
+
+ pRtlInitUnicodeString(&name, L"test3\\pipe");
+ attr.RootDirectory = hdirectory;
+ attr.ObjectName = &name;
+ timeout.QuadPart = -(LONG64)10000000;
+ status = pNtCreateNamedPipeFile(&hpipe, GENERIC_READ|GENERIC_WRITE, &attr, &io, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_CREATE, FILE_PIPE_FULL_DUPLEX, 0, 0, 0, 1, 256, 256, &timeout);
+ ok(status == STATUS_OBJECT_NAME_INVALID, "unexpected status from NtCreateNamedPipeFile: %08x\n", status);
+ if (!status)
+ CloseHandle(hpipe);
+
CloseHandle(hdirectory);
pRtlInitUnicodeString(&name, L"\\Device\\NamedPipe\\");
@@ -2476,6 +2545,10 @@ static void test_empty_name(void)
FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0 );
ok(!status, "Got unexpected status %#lx.\n", status);
+ pRtlInitUnicodeString(&name, L"nonexistent_pipe");
+ status = wait_pipe(hdirectory, &name, &zero_timeout);
+ ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "unexpected status for FSCTL_PIPE_WAIT on \\Device\\NamedPipe\\: %08x\n", status);
+
name.Buffer = NULL;
name.Length = 0;
name.MaximumLength = 0;
@@ -2566,9 +2639,24 @@ static void test_empty_name(void)
CloseHandle(hwrite);
CloseHandle(hpipe);
- CloseHandle(hdirectory);
CloseHandle(hpipe2);
CloseHandle(hwrite2);
+
+ pRtlInitUnicodeString(&name, L"test3\\pipe");
+ attr.RootDirectory = hdirectory;
+ attr.ObjectName = &name;
+ timeout.QuadPart = -(LONG64)10000000;
+ status = pNtCreateNamedPipeFile(&hpipe, GENERIC_READ|GENERIC_WRITE, &attr, &io, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_CREATE, FILE_PIPE_FULL_DUPLEX, 0, 0, 0, 1, 256, 256, &timeout);
+ todo_wine ok(!status, "unexpected failure from NtCreateNamedPipeFile: %08x\n", status);
+
+ handle = CreateFileA("\\\\.\\pipe\\test3\\pipe", GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, 0, 0 );
+ todo_wine ok(handle != INVALID_HANDLE_VALUE, "Failed to open NamedPipe (%u)\n", GetLastError());
+
+ CloseHandle(handle);
+ CloseHandle(hpipe);
+ CloseHandle(hdirectory);
}
START_TEST(pipe)
--
2.34.1
2
2
[PATCH v2 1/8] jscript: Store NULL disps as a different type of jsval_null.
by Gabriel Ivăncescu March 24, 2022
by Gabriel Ivăncescu March 24, 2022
March 24, 2022
This makes sure that object instances are always non-NULL and gets rid of
all such checks.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
Hopefully, I handled all cases and objects now can never be NULL. I tested
this with a bunch of test apps (some also needing the mshtml proxy object
patches), no difference in behavior or crashes were observed, so I think
it should cover all cases.
dlls/jscript/array.c | 13 +++++-----
dlls/jscript/dispex.c | 8 +++----
dlls/jscript/engine.c | 31 ++++++++----------------
dlls/jscript/function.c | 13 ++++++----
dlls/jscript/json.c | 11 +++++----
dlls/jscript/jsutils.c | 49 ++++++++++++++++----------------------
dlls/jscript/jsval.h | 13 ++++++++--
dlls/jscript/object.c | 25 +++++++++++--------
dlls/jscript/set.c | 2 +-
dlls/jscript/tests/api.js | 8 +++++++
dlls/jscript/tests/lang.js | 2 ++
11 files changed, 93 insertions(+), 82 deletions(-)
diff --git a/dlls/jscript/array.c b/dlls/jscript/array.c
index 9b97ef2..dcabc0d 100644
--- a/dlls/jscript/array.c
+++ b/dlls/jscript/array.c
@@ -704,7 +704,8 @@ static HRESULT Array_sort(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned
hres = JS_E_JSCRIPT_EXPECTED;
goto done;
}
- }else if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5 ? !is_undefined(argv[0]) : !is_null(argv[0])) {
+ }else if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5 ? !is_undefined(argv[0]) :
+ (!is_null(argv[0]) || is_null_disp(argv[0]))) {
WARN("invalid arg %s\n", debugstr_jsval(argv[0]));
hres = JS_E_JSCRIPT_EXPECTED;
goto done;
@@ -972,7 +973,7 @@ static HRESULT Array_forEach(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig
return hres;
/* Fixme check IsCallable */
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
+ if(!argc || !is_object_instance(argv[0])) {
FIXME("Invalid arg %s\n", debugstr_jsval(argc ? argv[0] : jsval_undefined()));
hres = E_INVALIDARG;
goto done;
@@ -980,7 +981,7 @@ static HRESULT Array_forEach(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig
callback = get_object(argv[0]);
if(argc > 1 && !is_undefined(argv[1])) {
- if(!is_object_instance(argv[1]) || !get_object(argv[1])) {
+ if(!is_object_instance(argv[1])) {
FIXME("Unsupported context this %s\n", debugstr_jsval(argv[1]));
hres = E_NOTIMPL;
goto done;
@@ -1087,7 +1088,7 @@ static HRESULT Array_map(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned
}
/* FIXME: check IsCallable */
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
+ if(!argc || !is_object_instance(argv[0])) {
FIXME("Invalid arg %s\n", debugstr_jsval(argc ? argv[0] : jsval_undefined()));
hres = E_INVALIDARG;
goto done;
@@ -1095,7 +1096,7 @@ static HRESULT Array_map(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigned
callback = get_object(argv[0]);
if(argc > 1) {
- if(is_object_instance(argv[1]) && get_object(argv[1])) {
+ if(is_object_instance(argv[1])) {
context_this = get_object(argv[1]);
}else if(!is_undefined(argv[1])) {
FIXME("Unsupported context this %s\n", debugstr_jsval(argv[1]));
@@ -1154,7 +1155,7 @@ static HRESULT Array_reduce(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsign
}
/* Fixme check IsCallable */
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
+ if(!argc || !is_object_instance(argv[0])) {
FIXME("Invalid arg %s\n", debugstr_jsval(argc ? argv[0] : jsval_undefined()));
hres = E_INVALIDARG;
goto done;
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index df2f65f..ef13e29 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -574,7 +574,7 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t
return invoke_prop_func(This->prototype, jsthis ? jsthis : (IDispatch *)&This->IDispatchEx_iface,
This->prototype->props+prop->u.ref, flags, argc, argv, r, caller);
case PROP_JSVAL: {
- if(!is_object_instance(prop->u.val) || !get_object(prop->u.val)) {
+ if(!is_object_instance(prop->u.val)) {
FIXME("invoke %s\n", debugstr_jsval(prop->u.val));
return E_FAIL;
}
@@ -593,7 +593,7 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t
if(FAILED(hres))
return hres;
- if(is_object_instance(val) && get_object(val)) {
+ if(is_object_instance(val)) {
hres = disp_call_value(This->ctx, get_object(val),
jsthis ? jsthis : (IDispatch*)&This->IDispatchEx_iface,
flags, argc, argv, r);
@@ -1927,7 +1927,7 @@ HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const built
return hres;
}
- if(is_object_instance(val) && get_object(val))
+ if(is_object_instance(val))
prot = iface_to_jsdisp(get_object(val));
else
prot = jsdisp_addref(ctx->object_prototype);
@@ -1987,7 +1987,7 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsig
}
flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
- hres = jsfunc->builtin_info->call(jsfunc->ctx, jsval_disp(jsthis), flags, argc, argv, r);
+ hres = jsfunc->builtin_info->call(jsfunc->ctx, jsthis ? jsval_disp(jsthis) : jsval_null(), flags, argc, argv, r);
}
return hres;
}
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c
index d894fbc..c483f2a 100644
--- a/dlls/jscript/engine.c
+++ b/dlls/jscript/engine.c
@@ -131,8 +131,6 @@ static HRESULT stack_pop_object(script_ctx_t *ctx, IDispatch **r)
v = stack_pop(ctx);
if(is_object_instance(v)) {
- if(!get_object(v))
- return JS_E_OBJECT_REQUIRED;
*r = get_object(v);
return S_OK;
}
@@ -539,10 +537,7 @@ HRESULT jsval_strict_equal(jsval_t lval, jsval_t rval, BOOL *ret)
TRACE("\n");
if(type != jsval_type(rval)) {
- if(is_null_instance(lval))
- *ret = is_null_instance(rval);
- else
- *ret = FALSE;
+ *ret = FALSE;
return S_OK;
}
@@ -1034,7 +1029,7 @@ static void set_error_value(script_ctx_t *ctx, jsval_t value)
ei->valid_value = TRUE;
ei->value = value;
- if(is_object_instance(value) && get_object(value) && (obj = to_jsdisp(get_object(value)))) {
+ if(is_object_instance(value) && (obj = to_jsdisp(get_object(value)))) {
UINT32 number;
jsstr_t *str;
jsval_t v;
@@ -1360,11 +1355,9 @@ static HRESULT interp_new(script_ctx_t *ctx)
/* NOTE: Should use to_object here */
if(is_null(constr))
- return JS_E_OBJECT_EXPECTED;
- else if(!is_object_instance(constr))
+ return is_null_disp(constr) ? JS_E_INVALID_PROPERTY : JS_E_OBJECT_EXPECTED;
+ if(!is_object_instance(constr))
return JS_E_INVALID_ACTION;
- else if(!get_object(constr))
- return JS_E_INVALID_PROPERTY;
clear_acc(ctx);
return disp_call_value(ctx, get_object(constr), NULL, DISPATCH_CONSTRUCT | DISPATCH_JSCRIPT_CALLEREXECSSOURCE,
@@ -1807,7 +1800,7 @@ static HRESULT interp_instanceof(script_ctx_t *ctx)
HRESULT hres;
v = stack_pop(ctx);
- if(!is_object_instance(v) || !get_object(v)) {
+ if(!is_object_instance(v)) {
jsval_release(v);
return JS_E_FUNCTION_EXPECTED;
}
@@ -1830,7 +1823,9 @@ static HRESULT interp_instanceof(script_ctx_t *ctx)
v = stack_pop(ctx);
- if(is_object_instance(prot)) {
+ if(is_null_disp(v))
+ hres = JS_E_OBJECT_EXPECTED;
+ else if(is_object_instance(prot)) {
if(is_object_instance(v))
tmp = iface_to_jsdisp(get_object(v));
for(iter = tmp; !ret && iter; iter = iter->prototype) {
@@ -1867,7 +1862,7 @@ static HRESULT interp_in(script_ctx_t *ctx)
TRACE("\n");
obj = stack_pop(ctx);
- if(!is_object_instance(obj) || !get_object(obj)) {
+ if(!is_object_instance(obj)) {
jsval_release(obj);
return JS_E_OBJECT_EXPECTED;
}
@@ -2126,7 +2121,7 @@ static HRESULT typeof_string(jsval_t v, const WCHAR **ret)
case JSV_OBJECT: {
jsdisp_t *dispex;
- if(get_object(v) && (dispex = iface_to_jsdisp(get_object(v)))) {
+ if((dispex = iface_to_jsdisp(get_object(v)))) {
*ret = is_class(dispex, JSCLASS_FUNCTION) ? L"function" : L"object";
jsdisp_release(dispex);
}else {
@@ -2326,12 +2321,6 @@ static HRESULT equal_values(script_ctx_t *ctx, jsval_t lval, jsval_t rval, BOOL
if(jsval_type(lval) == jsval_type(rval) || (is_number(lval) && is_number(rval)))
return jsval_strict_equal(lval, rval, ret);
- /* FIXME: NULL disps should be handled in more general way */
- if(is_object_instance(lval) && !get_object(lval))
- return equal_values(ctx, jsval_null(), rval, ret);
- if(is_object_instance(rval) && !get_object(rval))
- return equal_values(ctx, lval, jsval_null(), ret);
-
if((is_null(lval) && is_undefined(rval)) || (is_undefined(lval) && is_null(rval))) {
*ret = TRUE;
return S_OK;
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c
index fc8a85c..03c541c 100644
--- a/dlls/jscript/function.c
+++ b/dlls/jscript/function.c
@@ -256,7 +256,7 @@ 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);
- return function->vtbl->call(function->dispex.ctx, function, jsval_disp(jsthis), flags, argc, argv, r);
+ return function->vtbl->call(function->dispex.ctx, function, jsthis ? jsval_disp(jsthis) : jsval_null(), flags, argc, argv, r);
}
static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
@@ -336,6 +336,8 @@ static HRESULT Function_apply(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi
TRACE("\n");
+ if(is_null_disp(vthis))
+ return JS_E_OBJECT_REQUIRED;
if(!is_object_instance(vthis) || (!(function = function_this(vthis)) && to_jsdisp(get_object(vthis))))
return JS_E_FUNCTION_EXPECTED;
@@ -407,6 +409,8 @@ static HRESULT Function_call(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig
TRACE("\n");
+ if(is_null_disp(vthis))
+ return JS_E_OBJECT_REQUIRED;
if(!(function = function_this(vthis)))
return JS_E_FUNCTION_EXPECTED;
@@ -663,7 +667,7 @@ HRESULT create_builtin_function(script_ctx_t *ctx, builtin_invoke_t value_proc,
hres = jsdisp_define_data_property(&function->function.dispex, L"length", 0,
jsval_number(function->function.length));
if(SUCCEEDED(hres))
- hres = jsdisp_define_data_property(&function->function.dispex, L"prototype", 0, jsval_obj(prototype));
+ hres = jsdisp_define_data_property(&function->function.dispex, L"prototype", 0, prototype ? jsval_obj(prototype) : jsval_null());
if(FAILED(hres)) {
jsdisp_release(&function->function.dispex);
return hres;
@@ -725,8 +729,7 @@ static HRESULT InterpretedFunction_call(script_ctx_t *ctx, FunctionInstance *fun
this_obj = to_disp(new_obj);
}else if(is_object_instance(vthis)) {
this_obj = get_object(vthis);
- if(this_obj)
- IDispatch_AddRef(this_obj);
+ IDispatch_AddRef(this_obj);
}else if(ctx->version >= SCRIPTLANGUAGEVERSION_ES5 && !is_undefined(vthis) && !is_null(vthis)) {
hres = to_object(ctx, vthis, &this_obj);
if(FAILED(hres))
@@ -836,7 +839,7 @@ static HRESULT BindFunction_call(script_ctx_t *ctx, FunctionInstance *func, jsva
memcpy(call_args + function->argc, argv, argc * sizeof(*call_args));
}
- hres = function->target->vtbl->call(ctx, function->target, jsval_disp(function->this),
+ hres = function->target->vtbl->call(ctx, function->target, function->this ? jsval_disp(function->this) : jsval_null(),
flags, call_argc, call_args, r);
heap_free(call_args);
diff --git a/dlls/jscript/json.c b/dlls/jscript/json.c
index e0867eb..dfcc39d 100644
--- a/dlls/jscript/json.c
+++ b/dlls/jscript/json.c
@@ -404,7 +404,7 @@ static HRESULT maybe_to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *r)
jsdisp_t *obj;
HRESULT hres;
- if(!is_object_instance(val) || !get_object(val) || !(obj = iface_to_jsdisp(get_object(val))))
+ if(!is_object_instance(val) || !(obj = iface_to_jsdisp(get_object(val))))
return jsval_copy(val, r);
if(is_class(obj, JSCLASS_NUMBER)) {
@@ -640,7 +640,7 @@ static HRESULT stringify(stringify_ctx_t *ctx, jsdisp_t *object, const WCHAR *na
if(FAILED(hres))
return hres == DISP_E_UNKNOWNNAME ? S_FALSE : hres;
- if(is_object_instance(value) && get_object(value)) {
+ if(is_object_instance(value)) {
jsdisp_t *obj;
DISPID id;
@@ -681,7 +681,9 @@ static HRESULT stringify(stringify_ctx_t *ctx, jsdisp_t *object, const WCHAR *na
switch(jsval_type(value)) {
case JSV_NULL:
- if(!append_string(ctx, L"null"))
+ if(is_null_disp(value))
+ hres = S_FALSE;
+ else if(!append_string(ctx, L"null"))
hres = E_OUTOFMEMORY;
break;
case JSV_BOOL:
@@ -763,8 +765,7 @@ static HRESULT JSON_stringify(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi
return S_OK;
}
- if(argc >= 2 && is_object_instance(argv[1]) && get_object(argv[1]) &&
- (replacer = to_jsdisp(get_object(argv[1])))) {
+ if(argc >= 2 && is_object_instance(argv[1]) && (replacer = to_jsdisp(get_object(argv[1])))) {
if(is_callable(replacer)) {
stringify_ctx.replacer = jsdisp_addref(replacer);
}else if(is_class(replacer, JSCLASS_ARRAY)) {
diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c
index 6bc34da..7debf07 100644
--- a/dlls/jscript/jsutils.c
+++ b/dlls/jscript/jsutils.c
@@ -183,8 +183,7 @@ void jsval_release(jsval_t val)
{
switch(jsval_type(val)) {
case JSV_OBJECT:
- if(get_object(val))
- IDispatch_Release(get_object(val));
+ IDispatch_Release(get_object(val));
break;
case JSV_STRING:
jsstr_release(get_string(val));
@@ -229,8 +228,7 @@ HRESULT jsval_copy(jsval_t v, jsval_t *r)
*r = v;
return S_OK;
case JSV_OBJECT:
- if(get_object(v))
- IDispatch_AddRef(get_object(v));
+ IDispatch_AddRef(get_object(v));
*r = v;
return S_OK;
case JSV_STRING: {
@@ -282,8 +280,11 @@ HRESULT variant_to_jsval(VARIANT *var, jsval_t *r)
return S_OK;
}
case VT_DISPATCH: {
- if(V_DISPATCH(var))
- IDispatch_AddRef(V_DISPATCH(var));
+ if(!V_DISPATCH(var)) {
+ *r = jsval_null_disp();
+ return S_OK;
+ }
+ IDispatch_AddRef(V_DISPATCH(var));
*r = jsval_disp(V_DISPATCH(var));
return S_OK;
}
@@ -332,7 +333,7 @@ HRESULT variant_to_jsval(VARIANT *var, jsval_t *r)
return S_OK;
}
}else {
- *r = jsval_disp(NULL);
+ *r = jsval_null_disp();
return S_OK;
}
/* fall through */
@@ -348,13 +349,17 @@ HRESULT jsval_to_variant(jsval_t val, VARIANT *retv)
V_VT(retv) = VT_EMPTY;
return S_OK;
case JSV_NULL:
+ if(get_bool(val)) {
+ V_VT(retv) = VT_DISPATCH;
+ V_DISPATCH(retv) = NULL;
+ return S_OK;
+ }
V_VT(retv) = VT_NULL;
return S_OK;
case JSV_OBJECT:
V_VT(retv) = VT_DISPATCH;
- if(get_object(val))
- IDispatch_AddRef(get_object(val));
V_DISPATCH(retv) = get_object(val);
+ IDispatch_AddRef(get_object(val));
return S_OK;
case JSV_STRING:
V_VT(retv) = VT_BSTR;
@@ -394,11 +399,6 @@ HRESULT to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *ret, hint_t hint)
DISPID id;
HRESULT hres;
- if(!get_object(val)) {
- *ret = jsval_null();
- return S_OK;
- }
-
jsdisp = iface_to_jsdisp(get_object(val));
if(!jsdisp)
return disp_propget(ctx, get_object(val), DISPID_VALUE, ret);
@@ -459,7 +459,7 @@ HRESULT to_boolean(jsval_t val, BOOL *ret)
*ret = FALSE;
return S_OK;
case JSV_OBJECT:
- *ret = get_object(val) != NULL;
+ *ret = TRUE;
return S_OK;
case JSV_STRING:
*ret = jsstr_length(get_string(val)) != 0;
@@ -839,18 +839,8 @@ HRESULT to_object(script_ctx_t *ctx, jsval_t val, IDispatch **disp)
*disp = to_disp(dispex);
break;
case JSV_OBJECT:
- if(get_object(val)) {
- *disp = get_object(val);
- IDispatch_AddRef(*disp);
- }else {
- jsdisp_t *obj;
-
- hres = create_object(ctx, NULL, &obj);
- if(FAILED(hres))
- return hres;
-
- *disp = to_disp(obj);
- }
+ *disp = get_object(val);
+ IDispatch_AddRef(*disp);
break;
case JSV_BOOL:
hres = create_bool(ctx, get_bool(val), &dispex);
@@ -859,8 +849,11 @@ HRESULT to_object(script_ctx_t *ctx, jsval_t val, IDispatch **disp)
*disp = to_disp(dispex);
break;
- case JSV_UNDEFINED:
case JSV_NULL:
+ if(is_null_disp(val))
+ return JS_E_OBJECT_REQUIRED;
+ /* fall through */
+ case JSV_UNDEFINED:
WARN("object expected\n");
return JS_E_OBJECT_EXPECTED;
case JSV_VARIANT:
diff --git a/dlls/jscript/jsval.h b/dlls/jscript/jsval.h
index 9f451b1..4e00d08 100644
--- a/dlls/jscript/jsval.h
+++ b/dlls/jscript/jsval.h
@@ -131,6 +131,15 @@ static inline jsval_t jsval_null(void)
{
jsval_t ret;
__JSVAL_TYPE(ret) = JSV_NULL;
+ __JSVAL_BOOL(ret) = FALSE;
+ return ret;
+}
+
+static inline jsval_t jsval_null_disp(void)
+{
+ jsval_t ret;
+ __JSVAL_TYPE(ret) = JSV_NULL;
+ __JSVAL_BOOL(ret) = TRUE;
return ret;
}
@@ -178,9 +187,9 @@ static inline BOOL is_null(jsval_t v)
return __JSVAL_TYPE(v) == JSV_NULL;
}
-static inline BOOL is_null_instance(jsval_t v)
+static inline BOOL is_null_disp(jsval_t v)
{
- return is_null(v) || (is_object_instance(v) && !__JSVAL_OBJ(v));
+ return is_null(v) && __JSVAL_BOOL(v);
}
static inline BOOL is_string(jsval_t v)
diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c
index f8f1407..9d4a747 100644
--- a/dlls/jscript/object.c
+++ b/dlls/jscript/object.c
@@ -127,6 +127,11 @@ static HRESULT Object_valueOf(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsi
TRACE("\n");
+ if(is_null_disp(vthis)) {
+ if(r) *r = jsval_null_disp();
+ return S_OK;
+ }
+
hres = to_object(ctx, vthis, &disp);
if(FAILED(hres))
return hres;
@@ -554,7 +559,7 @@ static HRESULT jsdisp_define_properties(script_ctx_t *ctx, jsdisp_t *obj, jsval_
if(FAILED(hres))
break;
- if(!is_object_instance(desc_val) || !get_object(desc_val) || !(desc_obj = to_jsdisp(get_object(desc_val)))) {
+ if(!is_object_instance(desc_val) || !(desc_obj = to_jsdisp(get_object(desc_val)))) {
jsval_release(desc_val);
break;
}
@@ -631,7 +636,7 @@ static HRESULT Object_defineProperties(script_ctx_t *ctx, jsval_t vthis, WORD fl
jsdisp_t *obj;
HRESULT hres;
- if(argc < 1 || !is_object_instance(argv[0]) || !get_object(argv[0]) || !(obj = to_jsdisp(get_object(argv[0])))) {
+ if(argc < 1 || !is_object_instance(argv[0]) || !(obj = to_jsdisp(get_object(argv[0])))) {
FIXME("not an object\n");
return E_NOTIMPL;
}
@@ -779,7 +784,7 @@ static HRESULT object_keys(script_ctx_t *ctx, jsval_t arg, enum jsdisp_enum_type
jsstr_t *key;
HRESULT hres;
- if(!is_object_instance(arg) || !get_object(arg)) {
+ if(!is_object_instance(arg)) {
FIXME("invalid arguments %s\n", debugstr_jsval(arg));
return E_NOTIMPL;
}
@@ -838,7 +843,7 @@ static HRESULT Object_preventExtensions(script_ctx_t *ctx, jsval_t vthis, WORD f
{
jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
+ if(!argc || !is_object_instance(argv[0])) {
FIXME("invalid arguments\n");
return E_NOTIMPL;
}
@@ -861,7 +866,7 @@ static HRESULT Object_freeze(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsig
{
jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
+ if(!argc || !is_object_instance(argv[0])) {
WARN("argument is not an object\n");
return JS_E_OBJECT_EXPECTED;
}
@@ -884,7 +889,7 @@ static HRESULT Object_seal(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigne
{
jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
+ if(!argc || !is_object_instance(argv[0])) {
WARN("argument is not an object\n");
return JS_E_OBJECT_EXPECTED;
}
@@ -906,7 +911,7 @@ static HRESULT Object_isExtensible(script_ctx_t *ctx, jsval_t vthis, WORD flags,
{
jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
+ if(!argc || !is_object_instance(argv[0])) {
WARN("argument is not an object\n");
return JS_E_OBJECT_EXPECTED;
}
@@ -928,7 +933,7 @@ static HRESULT Object_isFrozen(script_ctx_t *ctx, jsval_t vthis, WORD flags, uns
{
jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
+ if(!argc || !is_object_instance(argv[0])) {
WARN("argument is not an object\n");
return JS_E_OBJECT_EXPECTED;
}
@@ -950,7 +955,7 @@ static HRESULT Object_isSealed(script_ctx_t *ctx, jsval_t vthis, WORD flags, uns
{
jsdisp_t *obj;
- if(!argc || !is_object_instance(argv[0]) || !get_object(argv[0])) {
+ if(!argc || !is_object_instance(argv[0])) {
WARN("argument is not an object\n");
return JS_E_OBJECT_EXPECTED;
}
@@ -1005,7 +1010,7 @@ static HRESULT ObjectConstr_value(script_ctx_t *ctx, jsval_t vthis, WORD flags,
jsdisp_t *obj;
if(argc) {
- if(!is_undefined(argv[0]) && !is_null(argv[0]) && (!is_object_instance(argv[0]) || get_object(argv[0]))) {
+ if(!is_undefined(argv[0]) && !is_null(argv[0])) {
IDispatch *disp;
hres = to_object(ctx, argv[0], &disp);
diff --git a/dlls/jscript/set.c b/dlls/jscript/set.c
index 35edcf8..7973d42 100644
--- a/dlls/jscript/set.c
+++ b/dlls/jscript/set.c
@@ -274,7 +274,7 @@ static HRESULT Map_forEach(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigne
TRACE("%p (%s)\n", map, debugstr_jsval(argc >= 1 ? argv[0] : jsval_undefined()));
- if(!is_object_instance(callback) || !get_object(callback)) {
+ if(!is_object_instance(callback)) {
FIXME("invalid callback %s\n", debugstr_jsval(callback));
return E_FAIL;
}
diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js
index 8e2b0d6..9eaeddd 100644
--- a/dlls/jscript/tests/api.js
+++ b/dlls/jscript/tests/api.js
@@ -1926,6 +1926,7 @@ ok(isNaN(tmp), "Math.tan(-Infinity) is not NaN");
[[true], "true"],
[[false], "false"],
[[null], "null"],
+ [[nullDisp], undefined],
[[1], "1"],
[["test"], "\"test\""],
[["test\"\\\b\f\n\r\t\u0002 !"], "\"test\\\"\\\\\\b\\f\\n\\r\\t\\u0002 !\""],
@@ -2367,6 +2368,9 @@ ok(bool.toString() === "true", "bool.toString() = " + bool.toString());
ok(bool.valueOf() === Boolean(1), "bool.valueOf() = " + bool.valueOf());
ok(bool.toLocaleString() === bool.toString(), "bool.toLocaleString() = " + bool.toLocaleString());
+tmp = Object.prototype.valueOf.call(nullDisp);
+ok(tmp === nullDisp, "nullDisp.valueOf != nullDisp");
+
ok(ActiveXObject instanceof Function, "ActiveXObject is not instance of Function");
ok(ActiveXObject.prototype instanceof Object, "ActiveXObject.prototype is not instance of Object");
@@ -2574,6 +2578,7 @@ testException(function() {createArray().getItem(3);}, "E_SUBSCRIPT_OUT_OF_RANGE"
testException(function() {date.setTime();}, "E_ARG_NOT_OPT");
testException(function() {date.setYear();}, "E_ARG_NOT_OPT");
testException(function() {arr.test();}, "E_NO_PROPERTY");
+testException(function() {[1,2,3].sort(nullDisp);}, "E_JSCRIPT_EXPECTED");
testException(function() {Number.prototype.toString.call(arr);}, "E_NOT_NUM");
testException(function() {Number.prototype.toFixed.call(arr);}, "E_NOT_NUM");
testException(function() {(new Number(3)).toString(1);}, "E_INVALID_CALL_ARG");
@@ -2587,6 +2592,9 @@ testException(function() {eval("nonexistingfunc()")}, "E_OBJECT_EXPECTED");
testException(function() {(new Object()) instanceof 3;}, "E_NOT_FUNC");
testException(function() {(new Object()) instanceof null;}, "E_NOT_FUNC");
testException(function() {(new Object()) instanceof nullDisp;}, "E_NOT_FUNC");
+testException(function() {nullDisp instanceof Object;}, "E_OBJECT_EXPECTED");
+testException(function() {Function.prototype.apply.call(nullDisp, Object, []);}, "E_OBJECT_REQUIRED");
+testException(function() {Function.prototype.call.call(nullDisp, Object);}, "E_OBJECT_REQUIRED");
testException(function() {"test" in 3;}, "E_OBJECT_EXPECTED");
testException(function() {"test" in null;}, "E_OBJECT_EXPECTED");
testException(function() {"test" in nullDisp;}, "E_OBJECT_EXPECTED");
diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js
index 23c9c79..cf08423 100644
--- a/dlls/jscript/tests/lang.js
+++ b/dlls/jscript/tests/lang.js
@@ -1906,6 +1906,8 @@ ok(getVT(true && nullDisp) === "VT_DISPATCH",
"getVT(0 && nullDisp) = " + getVT(true && nullDisp));
ok(!nullDisp === true, "!nullDisp = " + !nullDisp);
ok(String(nullDisp) === "null", "String(nullDisp) = " + String(nullDisp));
+ok(+nullDisp === 0, "+nullDisp !== 0");
+ok(''+nullDisp === "null", "''+nullDisp !== null");
ok(nullDisp != new Object(), "nullDisp == new Object()");
ok(new Object() != nullDisp, "new Object() == nullDisp");
ok((typeof Object(nullDisp)) === "object", "typeof Object(nullDisp) !== 'object'");
--
2.34.1
3
14
March 24, 2022
The MIM_DATA and MIM_LONGDATA notifications are sent via the
notification thread. The midi_handle_event syscall is temporary.
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsa.c | 2 +-
dlls/winealsa.drv/alsamidi.c | 172 +++++++++++++++++++++++++++++++++--
dlls/winealsa.drv/midi.c | 129 +-------------------------
dlls/winealsa.drv/unixlib.h | 4 +-
4 files changed, 167 insertions(+), 140 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c
index 5b592986c06..b18588ab1c0 100644
--- a/dlls/winealsa.drv/alsa.c
+++ b/dlls/winealsa.drv/alsa.c
@@ -2451,6 +2451,6 @@ unixlib_entry_t __wine_unix_call_funcs[] =
midi_notify_wait,
midi_seq_lock, /* temporary */
- midi_in_lock,
midi_seq_open,
+ midi_handle_event,
};
diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c
index e10779f63a1..30c46eee64d 100644
--- a/dlls/winealsa.drv/alsamidi.c
+++ b/dlls/winealsa.drv/alsamidi.c
@@ -72,6 +72,9 @@ static int port_in = -1;
static pthread_mutex_t notify_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t notify_cond = PTHREAD_COND_INITIALIZER;
static BOOL notify_quit;
+#define NOTIFY_BUFFER_SIZE 64 + 1 /* + 1 for the sentinel */
+static struct notify_context notify_buffer[NOTIFY_BUFFER_SIZE];
+static struct notify_context *notify_read = notify_buffer, *notify_write = notify_buffer;
static void seq_lock(void)
{
@@ -101,14 +104,6 @@ static void in_buffer_unlock(void)
pthread_mutex_unlock(&in_buffer_mutex);
}
-NTSTATUS midi_in_lock(void *args)
-{
- if (args) in_buffer_lock();
- else in_buffer_unlock();
-
- return STATUS_SUCCESS;
-}
-
static void set_in_notify(struct notify_context *notify, struct midi_src *src, WORD dev_id, WORD msg,
UINT_PTR param_1, UINT_PTR param_2)
{
@@ -123,11 +118,49 @@ static void set_in_notify(struct notify_context *notify, struct midi_src *src, W
notify->instance = src->midiDesc.dwInstance;
}
+/*
+ * notify buffer: The notification ring buffer is implemented so that
+ * there is always at least one unused sentinel before the current
+ * read position in order to allow detection of the full vs empty
+ * state.
+ */
+static struct notify_context *notify_buffer_next(struct notify_context *notify)
+{
+ if (++notify >= notify_buffer + ARRAY_SIZE(notify_buffer))
+ notify = notify_buffer;
+
+ return notify;
+}
+
+static void notify_buffer_add(struct notify_context *notify)
+{
+ struct notify_context *next = notify_buffer_next(notify_write);
+
+ if (next == notify_read) /* buffer is full - we can't issue a WARN() in a non-Win32 thread */
+ notify_read = notify_buffer_next(notify_read); /* drop the oldest notification */
+ *notify_write = *notify;
+ notify_write = next;
+}
+
+static BOOL notify_buffer_empty(void)
+{
+ return notify_read == notify_write;
+}
+
+static BOOL notify_buffer_remove(struct notify_context *notify)
+{
+ if (notify_buffer_empty()) return FALSE;
+
+ *notify = *notify_read;
+ notify_read = notify_buffer_next(notify_read);
+ return TRUE;
+}
+
static void notify_post(struct notify_context *notify)
{
pthread_mutex_lock(¬ify_mutex);
- if (notify) FIXME("Not yet handled\n");
+ if (notify) notify_buffer_add(notify);
else notify_quit = TRUE;
pthread_cond_signal(¬ify_cond);
@@ -889,6 +922,124 @@ static UINT midi_out_reset(WORD dev_id)
return MMSYSERR_NOERROR;
}
+static void handle_sysex_event(struct midi_src *src, BYTE *data, UINT len)
+{
+ UINT pos = 0, copy_len, current_time = NtGetTickCount() - src->startTime;
+ struct notify_context notify;
+ MIDIHDR *hdr;
+
+ in_buffer_lock();
+
+ while (len)
+ {
+ hdr = src->lpQueueHdr;
+ if (!hdr) break;
+
+ copy_len = min(len, hdr->dwBufferLength - hdr->dwBytesRecorded);
+ memcpy(hdr->lpData + hdr->dwBytesRecorded, data + pos, copy_len);
+ hdr->dwBytesRecorded += copy_len;
+ len -= copy_len;
+ pos += copy_len;
+
+ if ((hdr->dwBytesRecorded == hdr->dwBufferLength) ||
+ (*(BYTE*)(hdr->lpData + hdr->dwBytesRecorded - 1) == 0xF7))
+ { /* buffer full or end of sysex message */
+ src->lpQueueHdr = hdr->lpNext;
+ hdr->dwFlags &= ~MHDR_INQUEUE;
+ hdr->dwFlags |= MHDR_DONE;
+ set_in_notify(¬ify, src, src - srcs, MIM_LONGDATA, (DWORD_PTR)hdr, current_time);
+ notify_post(¬ify);
+ }
+ }
+
+ in_buffer_unlock();
+}
+
+static void handle_regular_event(struct midi_src *src, snd_seq_event_t *ev)
+{
+ UINT data = 0, value, current_time = NtGetTickCount() - src->startTime;
+ struct notify_context notify;
+
+ switch (ev->type)
+ {
+ case SND_SEQ_EVENT_NOTEOFF:
+ data = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_OFF | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_NOTEON:
+ data = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_ON | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_KEYPRESS:
+ data = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_PRESSURE | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_CONTROLLER:
+ data = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CONTROL | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_PITCHBEND:
+ value = ev->data.control.value + 0x2000;
+ data = (((value >> 7) & 0x7f) << 16) | ((value & 0x7f) << 8) | MIDI_CMD_BENDER | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_PGMCHANGE:
+ data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_PGM_CHANGE | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_CHANPRESS:
+ data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_CHANNEL_PRESSURE | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_CLOCK:
+ data = 0xF8;
+ break;
+ case SND_SEQ_EVENT_START:
+ data = 0xFA;
+ break;
+ case SND_SEQ_EVENT_CONTINUE:
+ data = 0xFB;
+ break;
+ case SND_SEQ_EVENT_STOP:
+ data = 0xFC;
+ break;
+ case SND_SEQ_EVENT_SONGPOS:
+ data = (((ev->data.control.value >> 7) & 0x7f) << 16) | ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_SONG_POS;
+ break;
+ case SND_SEQ_EVENT_SONGSEL:
+ data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_SONG_SELECT;
+ break;
+ case SND_SEQ_EVENT_RESET:
+ data = 0xFF;
+ break;
+ case SND_SEQ_EVENT_QFRAME:
+ data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_MTC_QUARTER;
+ break;
+ case SND_SEQ_EVENT_SENSING:
+ /* Noting to do */
+ break;
+ }
+
+ if (data != 0)
+ {
+ set_in_notify(¬ify, src, src - srcs, MIM_DATA, data, current_time);
+ notify_post(¬ify);
+ }
+}
+
+NTSTATUS midi_handle_event(void *args)
+{
+ snd_seq_event_t *ev = args;
+ struct midi_src *src;
+
+ /* Find the target device */
+ for (src = srcs; src < srcs + num_srcs; src++)
+ if ((ev->source.client == src->addr.client) && (ev->source.port == src->addr.port))
+ break;
+ if ((src == srcs + num_srcs) || (src->state != 1))
+ return STATUS_SUCCESS;
+
+ if (ev->type == SND_SEQ_EVENT_SYSEX)
+ handle_sysex_event(src, ev->data.ext.ptr, ev->data.ext.len);
+ else
+ handle_regular_event(src, ev);
+
+ return STATUS_SUCCESS;
+}
+
static UINT midi_in_add_buffer(WORD dev_id, MIDIHDR *hdr, UINT hdr_size)
{
struct midi_src *src;
@@ -1131,10 +1282,11 @@ NTSTATUS midi_notify_wait(void *args)
pthread_mutex_lock(¬ify_mutex);
- while (!notify_quit)
+ while (!notify_quit && notify_buffer_empty())
pthread_cond_wait(¬ify_cond, ¬ify_mutex);
*params->quit = notify_quit;
+ if (!notify_quit) notify_buffer_remove(params->notify);
pthread_mutex_unlock(¬ify_mutex);
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index 77ab9720bcc..8009b23ce3d 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -67,16 +67,6 @@ static void seq_unlock(void)
ALSA_CALL(midi_seq_lock, (void *)(UINT_PTR)0);
}
-static void in_buffer_lock(void)
-{
- ALSA_CALL(midi_in_lock, (void *)(UINT_PTR)1);
-}
-
-static void in_buffer_unlock(void)
-{
- ALSA_CALL(midi_in_lock, (void *)(UINT_PTR)0);
-}
-
static void notify_client(struct notify_context *notify)
{
TRACE("dev_id = %d msg = %d param1 = %04lX param2 = %04lX\n", notify->dev_id, notify->msg, notify->param_1, notify->param_2);
@@ -122,11 +112,6 @@ static void MIDI_NotifyClient(UINT wDevID, WORD wMsg,
switch (wMsg) {
case MIM_OPEN:
case MIM_CLOSE:
- case MIM_DATA:
- case MIM_LONGDATA:
- case MIM_ERROR:
- case MIM_LONGERROR:
- case MIM_MOREDATA:
if (wDevID > MIDM_NumDevs) return;
dwCallBack = MidiInDev[wDevID].midiDesc.dwCallback;
@@ -170,117 +155,6 @@ static int midiCloseSeq(void)
return 0;
}
-static void handle_sysex_event(struct midi_src *src, BYTE *data, UINT len)
-{
- UINT pos = 0, copy_len, current_time = NtGetTickCount() - src->startTime;
- MIDIHDR *hdr;
-
- in_buffer_lock();
-
- while (len)
- {
- hdr = src->lpQueueHdr;
- if (!hdr) break;
-
- copy_len = min(len, hdr->dwBufferLength - hdr->dwBytesRecorded);
- memcpy(hdr->lpData + hdr->dwBytesRecorded, data + pos, copy_len);
- hdr->dwBytesRecorded += copy_len;
- len -= copy_len;
- pos += copy_len;
-
- if ((hdr->dwBytesRecorded == hdr->dwBufferLength) ||
- (*(BYTE*)(hdr->lpData + hdr->dwBytesRecorded - 1) == 0xF7))
- { /* buffer full or end of sysex message */
- src->lpQueueHdr = hdr->lpNext;
- hdr->dwFlags &= ~MHDR_INQUEUE;
- hdr->dwFlags |= MHDR_DONE;
- MIDI_NotifyClient(src - MidiInDev, MIM_LONGDATA, (DWORD_PTR)hdr, current_time);
- }
- }
-
- in_buffer_unlock();
-}
-
-static void handle_regular_event(struct midi_src *src, snd_seq_event_t *ev)
-{
- UINT data = 0, value, current_time = NtGetTickCount() - src->startTime;
-
- switch (ev->type)
- {
- case SND_SEQ_EVENT_NOTEOFF:
- data = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_OFF | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_NOTEON:
- data = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_ON | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_KEYPRESS:
- data = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_PRESSURE | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_CONTROLLER:
- data = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CONTROL | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_PITCHBEND:
- value = ev->data.control.value + 0x2000;
- data = (((value >> 7) & 0x7f) << 16) | ((value & 0x7f) << 8) | MIDI_CMD_BENDER | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_PGMCHANGE:
- data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_PGM_CHANGE | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_CHANPRESS:
- data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_CHANNEL_PRESSURE | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_CLOCK:
- data = 0xF8;
- break;
- case SND_SEQ_EVENT_START:
- data = 0xFA;
- break;
- case SND_SEQ_EVENT_CONTINUE:
- data = 0xFB;
- break;
- case SND_SEQ_EVENT_STOP:
- data = 0xFC;
- break;
- case SND_SEQ_EVENT_SONGPOS:
- data = (((ev->data.control.value >> 7) & 0x7f) << 16) | ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_SONG_POS;
- break;
- case SND_SEQ_EVENT_SONGSEL:
- data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_SONG_SELECT;
- break;
- case SND_SEQ_EVENT_RESET:
- data = 0xFF;
- break;
- case SND_SEQ_EVENT_QFRAME:
- data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_MTC_QUARTER;
- break;
- case SND_SEQ_EVENT_SENSING:
- /* Noting to do */
- break;
- }
-
- if (data != 0)
- {
- MIDI_NotifyClient(src - MidiInDev, MIM_DATA, data, current_time);
- }
-}
-
-static void handle_midi_event(snd_seq_event_t *ev)
-{
- struct midi_src *src;
-
- /* Find the target device */
- for (src = MidiInDev; src < MidiInDev + MIDM_NumDevs; src++)
- if ((ev->source.client == src->addr.client) && (ev->source.port == src->addr.port))
- break;
- if ((src == MidiInDev + MIDM_NumDevs) || (src->state != 1))
- return;
-
- if (ev->type == SND_SEQ_EVENT_SYSEX)
- handle_sysex_event(src, ev->data.ext.ptr, ev->data.ext.len);
- else
- handle_regular_event(src, ev);
-}
-
static DWORD WINAPI midRecThread(void *arg)
{
snd_seq_t *midi_seq = arg;
@@ -320,7 +194,7 @@ static DWORD WINAPI midRecThread(void *arg)
seq_unlock();
if (ev) {
- handle_midi_event(ev);
+ ALSA_CALL(midi_handle_event, ev);
snd_seq_free_event(ev);
}
@@ -571,6 +445,7 @@ static DWORD WINAPI notify_thread(void *p)
{
ALSA_CALL(midi_notify_wait, ¶ms);
if (quit) break;
+ if (notify.send_notify) notify_client(¬ify);
}
return 0;
}
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
index 68ab650d2f6..46f256a1c6a 100644
--- a/dlls/winealsa.drv/unixlib.h
+++ b/dlls/winealsa.drv/unixlib.h
@@ -310,8 +310,8 @@ enum alsa_funcs
alsa_midi_notify_wait,
alsa_midi_seq_lock, /* temporary */
- alsa_midi_in_lock,
alsa_midi_seq_open,
+ alsa_midi_handle_event,
};
NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
@@ -321,8 +321,8 @@ NTSTATUS midi_in_message(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_notify_wait(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_seq_lock(void *args) DECLSPEC_HIDDEN;
-NTSTATUS midi_in_lock(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_seq_open(void *args) DECLSPEC_HIDDEN;
+NTSTATUS midi_handle_event(void *args) DECLSPEC_HIDDEN;
extern unixlib_handle_t alsa_handle;
--
2.25.1
2
1
March 24, 2022
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/midi.c | 207 ++++++++++++++++++++-------------------
1 file changed, 104 insertions(+), 103 deletions(-)
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index ca31def8d16..77ab9720bcc 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -170,114 +170,115 @@ static int midiCloseSeq(void)
return 0;
}
+static void handle_sysex_event(struct midi_src *src, BYTE *data, UINT len)
+{
+ UINT pos = 0, copy_len, current_time = NtGetTickCount() - src->startTime;
+ MIDIHDR *hdr;
+
+ in_buffer_lock();
+
+ while (len)
+ {
+ hdr = src->lpQueueHdr;
+ if (!hdr) break;
+
+ copy_len = min(len, hdr->dwBufferLength - hdr->dwBytesRecorded);
+ memcpy(hdr->lpData + hdr->dwBytesRecorded, data + pos, copy_len);
+ hdr->dwBytesRecorded += copy_len;
+ len -= copy_len;
+ pos += copy_len;
+
+ if ((hdr->dwBytesRecorded == hdr->dwBufferLength) ||
+ (*(BYTE*)(hdr->lpData + hdr->dwBytesRecorded - 1) == 0xF7))
+ { /* buffer full or end of sysex message */
+ src->lpQueueHdr = hdr->lpNext;
+ hdr->dwFlags &= ~MHDR_INQUEUE;
+ hdr->dwFlags |= MHDR_DONE;
+ MIDI_NotifyClient(src - MidiInDev, MIM_LONGDATA, (DWORD_PTR)hdr, current_time);
+ }
+ }
+
+ in_buffer_unlock();
+}
+
+static void handle_regular_event(struct midi_src *src, snd_seq_event_t *ev)
+{
+ UINT data = 0, value, current_time = NtGetTickCount() - src->startTime;
+
+ switch (ev->type)
+ {
+ case SND_SEQ_EVENT_NOTEOFF:
+ data = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_OFF | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_NOTEON:
+ data = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_ON | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_KEYPRESS:
+ data = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_PRESSURE | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_CONTROLLER:
+ data = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CONTROL | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_PITCHBEND:
+ value = ev->data.control.value + 0x2000;
+ data = (((value >> 7) & 0x7f) << 16) | ((value & 0x7f) << 8) | MIDI_CMD_BENDER | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_PGMCHANGE:
+ data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_PGM_CHANGE | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_CHANPRESS:
+ data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_CHANNEL_PRESSURE | ev->data.control.channel;
+ break;
+ case SND_SEQ_EVENT_CLOCK:
+ data = 0xF8;
+ break;
+ case SND_SEQ_EVENT_START:
+ data = 0xFA;
+ break;
+ case SND_SEQ_EVENT_CONTINUE:
+ data = 0xFB;
+ break;
+ case SND_SEQ_EVENT_STOP:
+ data = 0xFC;
+ break;
+ case SND_SEQ_EVENT_SONGPOS:
+ data = (((ev->data.control.value >> 7) & 0x7f) << 16) | ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_SONG_POS;
+ break;
+ case SND_SEQ_EVENT_SONGSEL:
+ data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_SONG_SELECT;
+ break;
+ case SND_SEQ_EVENT_RESET:
+ data = 0xFF;
+ break;
+ case SND_SEQ_EVENT_QFRAME:
+ data = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_MTC_QUARTER;
+ break;
+ case SND_SEQ_EVENT_SENSING:
+ /* Noting to do */
+ break;
+ }
+
+ if (data != 0)
+ {
+ MIDI_NotifyClient(src - MidiInDev, MIM_DATA, data, current_time);
+ }
+}
+
static void handle_midi_event(snd_seq_event_t *ev)
{
- WORD wDevID;
+ struct midi_src *src;
/* Find the target device */
- for (wDevID = 0; wDevID < MIDM_NumDevs; wDevID++)
- if ( (ev->source.client == MidiInDev[wDevID].addr.client) && (ev->source.port == MidiInDev[wDevID].addr.port) )
- break;
- if ((wDevID == MIDM_NumDevs) || (MidiInDev[wDevID].state != 1))
- FIXME("Unexpected event received, type = %x from %d:%d\n", ev->type, ev->source.client, ev->source.port);
- else {
- DWORD dwTime, toSend = 0;
- int value = 0;
- /* FIXME: Should use ev->time instead for better accuracy */
- dwTime = GetTickCount() - MidiInDev[wDevID].startTime;
- TRACE("Event received, type = %x, device = %d\n", ev->type, wDevID);
- switch(ev->type)
- {
- case SND_SEQ_EVENT_NOTEOFF:
- toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_OFF | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_NOTEON:
- toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_ON | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_KEYPRESS:
- toSend = (ev->data.note.velocity << 16) | (ev->data.note.note << 8) | MIDI_CMD_NOTE_PRESSURE | ev->data.control.channel;
+ for (src = MidiInDev; src < MidiInDev + MIDM_NumDevs; src++)
+ if ((ev->source.client == src->addr.client) && (ev->source.port == src->addr.port))
break;
- case SND_SEQ_EVENT_CONTROLLER:
- toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CONTROL | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_PITCHBEND:
- value = ev->data.control.value + 0x2000;
- toSend = (((value >> 7) & 0x7f) << 16) | ((value & 0x7f) << 8) | MIDI_CMD_BENDER | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_PGMCHANGE:
- toSend = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_PGM_CHANGE | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_CHANPRESS:
- toSend = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_CHANNEL_PRESSURE | ev->data.control.channel;
- break;
- case SND_SEQ_EVENT_CLOCK:
- toSend = 0xF8;
- break;
- case SND_SEQ_EVENT_START:
- toSend = 0xFA;
- break;
- case SND_SEQ_EVENT_CONTINUE:
- toSend = 0xFB;
- break;
- case SND_SEQ_EVENT_STOP:
- toSend = 0xFC;
- break;
- case SND_SEQ_EVENT_SONGPOS:
- toSend = (((ev->data.control.value >> 7) & 0x7f) << 16) | ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_SONG_POS;
- break;
- case SND_SEQ_EVENT_SONGSEL:
- toSend = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_SONG_SELECT;
- break;
- case SND_SEQ_EVENT_RESET:
- toSend = 0xFF;
- break;
- case SND_SEQ_EVENT_QFRAME:
- toSend = ((ev->data.control.value & 0x7f) << 8) | MIDI_CMD_COMMON_MTC_QUARTER;
- break;
- case SND_SEQ_EVENT_SYSEX:
- {
- int pos = 0;
- int len = ev->data.ext.len;
- LPBYTE ptr = ev->data.ext.ptr;
- LPMIDIHDR lpMidiHdr;
-
- in_buffer_lock();
- while (len) {
- if ((lpMidiHdr = MidiInDev[wDevID].lpQueueHdr) != NULL) {
- int copylen = min(len, lpMidiHdr->dwBufferLength - lpMidiHdr->dwBytesRecorded);
- memcpy(lpMidiHdr->lpData + lpMidiHdr->dwBytesRecorded, ptr + pos, copylen);
- lpMidiHdr->dwBytesRecorded += copylen;
- len -= copylen;
- pos += copylen;
- /* We check if we reach the end of buffer or the end of sysex before notifying
- * to handle the case where ALSA split the sysex into several events */
- if ((lpMidiHdr->dwBytesRecorded == lpMidiHdr->dwBufferLength) ||
- (*(BYTE*)(lpMidiHdr->lpData + lpMidiHdr->dwBytesRecorded - 1) == 0xF7)) {
- MidiInDev[wDevID].lpQueueHdr = lpMidiHdr->lpNext;
- lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
- lpMidiHdr->dwFlags |= MHDR_DONE;
- MIDI_NotifyClient(wDevID, MIM_LONGDATA, (DWORD_PTR)lpMidiHdr, dwTime);
- }
- } else {
- FIXME("Sysex data received but no buffer to store it!\n");
- break;
- }
- }
- in_buffer_unlock();
- }
- break;
- case SND_SEQ_EVENT_SENSING:
- /* Noting to do */
- break;
- default:
- FIXME("Unhandled event received, type = %x\n", ev->type);
- break;
- }
- if (toSend != 0) {
- TRACE("Received event %08x from %d:%d\n", toSend, ev->source.client, ev->source.port);
- MIDI_NotifyClient(wDevID, MIM_DATA, toSend, dwTime);
- }
- }
+ if ((src == MidiInDev + MIDM_NumDevs) || (src->state != 1))
+ return;
+
+ if (ev->type == SND_SEQ_EVENT_SYSEX)
+ handle_sysex_event(src, ev->data.ext.ptr, ev->data.ext.len);
+ else
+ handle_regular_event(src, ev);
}
static DWORD WINAPI midRecThread(void *arg)
--
2.25.1
2
1
Currently the thread just blocks until told to quit by midi_release.
Eventually this thread will dispatch the MIM_DATA and MIM_LONGDATA
notifications.
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsa.c | 2 ++
dlls/winealsa.drv/alsamidi.c | 39 ++++++++++++++++++++++++++++++++++++
dlls/winealsa.drv/midi.c | 24 +++++++++++++++++++---
dlls/winealsa.drv/unixlib.h | 10 +++++++++
4 files changed, 72 insertions(+), 3 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c
index eb16203dbf9..5b592986c06 100644
--- a/dlls/winealsa.drv/alsa.c
+++ b/dlls/winealsa.drv/alsa.c
@@ -2445,8 +2445,10 @@ unixlib_entry_t __wine_unix_call_funcs[] =
is_started,
get_prop_value,
midi_init,
+ midi_release,
midi_out_message,
midi_in_message,
+ midi_notify_wait,
midi_seq_lock, /* temporary */
midi_in_lock,
diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c
index ccdb35731d1..e10779f63a1 100644
--- a/dlls/winealsa.drv/alsamidi.c
+++ b/dlls/winealsa.drv/alsamidi.c
@@ -69,6 +69,10 @@ static snd_seq_t *midi_seq;
static unsigned int seq_refs;
static int port_in = -1;
+static pthread_mutex_t notify_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t notify_cond = PTHREAD_COND_INITIALIZER;
+static BOOL notify_quit;
+
static void seq_lock(void)
{
pthread_mutex_lock(&seq_mutex);
@@ -119,6 +123,17 @@ static void set_in_notify(struct notify_context *notify, struct midi_src *src, W
notify->instance = src->midiDesc.dwInstance;
}
+static void notify_post(struct notify_context *notify)
+{
+ pthread_mutex_lock(¬ify_mutex);
+
+ if (notify) FIXME("Not yet handled\n");
+ else notify_quit = TRUE;
+ pthread_cond_signal(¬ify_cond);
+
+ pthread_mutex_unlock(¬ify_mutex);
+}
+
static snd_seq_t *seq_open(int *port_in_ret)
{
static int midi_warn;
@@ -405,6 +420,14 @@ NTSTATUS midi_init(void *args)
return STATUS_SUCCESS;
}
+NTSTATUS midi_release(void *args)
+{
+ /* stop the notify_wait thread */
+ notify_post(NULL);
+
+ return STATUS_SUCCESS;
+}
+
static void set_out_notify(struct notify_context *notify, struct midi_dest *dest, WORD dev_id, WORD msg,
UINT_PTR param_1, UINT_PTR param_2)
{
@@ -1101,3 +1124,19 @@ NTSTATUS midi_in_message(void *args)
return STATUS_SUCCESS;
}
+
+NTSTATUS midi_notify_wait(void *args)
+{
+ struct midi_notify_wait_params *params = args;
+
+ pthread_mutex_lock(¬ify_mutex);
+
+ while (!notify_quit)
+ pthread_cond_wait(¬ify_cond, ¬ify_mutex);
+
+ *params->quit = notify_quit;
+
+ pthread_mutex_unlock(¬ify_mutex);
+
+ return STATUS_SUCCESS;
+}
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index 35678588549..ca31def8d16 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -557,18 +557,36 @@ DWORD WINAPI ALSA_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
return err;
}
+static DWORD WINAPI notify_thread(void *p)
+{
+ struct midi_notify_wait_params params;
+ struct notify_context notify;
+ BOOL quit;
+
+ params.notify = ¬ify;
+ params.quit = &quit;
+
+ while (1)
+ {
+ ALSA_CALL(midi_notify_wait, ¶ms);
+ if (quit) break;
+ }
+ return 0;
+}
+
/**************************************************************************
* DriverProc (WINEALSA.@)
*/
LRESULT CALLBACK ALSA_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
LPARAM dwParam1, LPARAM dwParam2)
{
-/* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */
-/* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
-
switch(wMsg) {
case DRV_LOAD:
+ CloseHandle(CreateThread(NULL, 0, notify_thread, NULL, 0, NULL));
+ return 1;
case DRV_FREE:
+ ALSA_CALL(midi_release, NULL);
+ return 1;
case DRV_OPEN:
case DRV_CLOSE:
case DRV_ENABLE:
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
index 6d5bcb64cf0..68ab650d2f6 100644
--- a/dlls/winealsa.drv/unixlib.h
+++ b/dlls/winealsa.drv/unixlib.h
@@ -265,6 +265,12 @@ struct midi_in_message_params
struct notify_context *notify;
};
+struct midi_notify_wait_params
+{
+ BOOL *quit;
+ struct notify_context *notify;
+};
+
struct midi_seq_open_params
{
int close;
@@ -298,8 +304,10 @@ enum alsa_funcs
alsa_is_started,
alsa_get_prop_value,
alsa_midi_init,
+ alsa_midi_release,
alsa_midi_out_message,
alsa_midi_in_message,
+ alsa_midi_notify_wait,
alsa_midi_seq_lock, /* temporary */
alsa_midi_in_lock,
@@ -307,8 +315,10 @@ enum alsa_funcs
};
NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
+NTSTATUS midi_release(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_out_message(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_in_message(void *args) DECLSPEC_HIDDEN;
+NTSTATUS midi_notify_wait(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_seq_lock(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_in_lock(void *args) DECLSPEC_HIDDEN;
--
2.25.1
2
1
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsamidi.c | 17 +++++++++++++++++
dlls/winealsa.drv/midi.c | 16 ----------------
2 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c
index d647ba79a9e..ccdb35731d1 100644
--- a/dlls/winealsa.drv/alsamidi.c
+++ b/dlls/winealsa.drv/alsamidi.c
@@ -957,6 +957,20 @@ static UINT midi_in_start(WORD dev_id)
return MMSYSERR_NOERROR;
}
+static UINT midi_in_stop(WORD dev_id)
+{
+ struct midi_src *src;
+
+ TRACE("(%04X);\n", dev_id);
+
+ if (dev_id >= num_srcs) return MMSYSERR_BADDEVICEID;
+ src = srcs + dev_id;
+ if (src->state == -1) return MIDIERR_NODEVICE;
+
+ src->state = 0;
+ return MMSYSERR_NOERROR;
+}
+
static DWORD midi_in_reset(WORD dev_id, struct notify_context *notify)
{
UINT cur_time = NtGetTickCount();
@@ -1074,6 +1088,9 @@ NTSTATUS midi_in_message(void *args)
case MIDM_START:
*params->err = midi_in_start(params->dev_id);
break;
+ case MIDM_STOP:
+ *params->err = midi_in_stop(params->dev_id);
+ break;
case MIDM_RESET:
*params->err = midi_in_reset(params->dev_id, params->notify);
break;
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index 88b23f52ec1..35678588549 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -459,20 +459,6 @@ static DWORD midClose(WORD wDevID)
return ret;
}
-/**************************************************************************
- * midStop [internal]
- */
-static DWORD midStop(WORD wDevID)
-{
- TRACE("(%04X);\n", wDevID);
-
- if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;
- if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;
-
- MidiInDev[wDevID].state = 0;
- return MMSYSERR_NOERROR;
-}
-
/*======================================================================*
* MIDI entry points *
*======================================================================*/
@@ -518,8 +504,6 @@ DWORD WINAPI ALSA_midMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
return midOpen(wDevID, (LPMIDIOPENDESC)dwParam1, dwParam2);
case MIDM_CLOSE:
return midClose(wDevID);
- case MIDM_STOP:
- return midStop(wDevID);
}
params.dev_id = wDevID;
--
2.25.1
2
1
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsamidi.c | 18 ++++++++++++++++++
dlls/winealsa.drv/midi.c | 17 -----------------
2 files changed, 18 insertions(+), 17 deletions(-)
diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c
index 535699a4059..d647ba79a9e 100644
--- a/dlls/winealsa.drv/alsamidi.c
+++ b/dlls/winealsa.drv/alsamidi.c
@@ -942,6 +942,21 @@ static UINT midi_in_get_devcaps(WORD dev_id, MIDIINCAPSW *caps, UINT size)
return MMSYSERR_NOERROR;
}
+static UINT midi_in_start(WORD dev_id)
+{
+ struct midi_src *src;
+
+ TRACE("(%04X);\n", dev_id);
+
+ if (dev_id >= num_srcs) return MMSYSERR_BADDEVICEID;
+ src = srcs + dev_id;
+ if (src->state == -1) return MIDIERR_NODEVICE;
+
+ src->state = 1;
+ src->startTime = NtGetTickCount();
+ return MMSYSERR_NOERROR;
+}
+
static DWORD midi_in_reset(WORD dev_id, struct notify_context *notify)
{
UINT cur_time = NtGetTickCount();
@@ -1056,6 +1071,9 @@ NTSTATUS midi_in_message(void *args)
case MIDM_GETNUMDEVS:
*params->err = num_srcs;
break;
+ case MIDM_START:
+ *params->err = midi_in_start(params->dev_id);
+ break;
case MIDM_RESET:
*params->err = midi_in_reset(params->dev_id, params->notify);
break;
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index 5639bf67369..88b23f52ec1 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -459,21 +459,6 @@ static DWORD midClose(WORD wDevID)
return ret;
}
-/**************************************************************************
- * midStart [internal]
- */
-static DWORD midStart(WORD wDevID)
-{
- TRACE("(%04X);\n", wDevID);
-
- if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;
- if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;
-
- MidiInDev[wDevID].state = 1;
- MidiInDev[wDevID].startTime = GetTickCount();
- return MMSYSERR_NOERROR;
-}
-
/**************************************************************************
* midStop [internal]
*/
@@ -533,8 +518,6 @@ DWORD WINAPI ALSA_midMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
return midOpen(wDevID, (LPMIDIOPENDESC)dwParam1, dwParam2);
case MIDM_CLOSE:
return midClose(wDevID);
- case MIDM_START:
- return midStart(wDevID);
case MIDM_STOP:
return midStop(wDevID);
}
--
2.25.1
2
1
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsamidi.c | 49 ++++++++++++++++++++++++++++++++++++
dlls/winealsa.drv/midi.c | 35 ++++++--------------------
dlls/winealsa.drv/unixlib.h | 1 +
3 files changed, 57 insertions(+), 28 deletions(-)
diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c
index 80e677b3064..535699a4059 100644
--- a/dlls/winealsa.drv/alsamidi.c
+++ b/dlls/winealsa.drv/alsamidi.c
@@ -105,6 +105,20 @@ NTSTATUS midi_in_lock(void *args)
return STATUS_SUCCESS;
}
+static void set_in_notify(struct notify_context *notify, struct midi_src *src, WORD dev_id, WORD msg,
+ UINT_PTR param_1, UINT_PTR param_2)
+{
+ notify->send_notify = TRUE;
+ notify->dev_id = dev_id;
+ notify->msg = msg;
+ notify->param_1 = param_1;
+ notify->param_2 = param_2;
+ notify->callback = src->midiDesc.dwCallback;
+ notify->flags = src->wFlags;
+ notify->device = src->midiDesc.hMidi;
+ notify->instance = src->midiDesc.dwInstance;
+}
+
static snd_seq_t *seq_open(int *port_in_ret)
{
static int midi_warn;
@@ -928,6 +942,36 @@ static UINT midi_in_get_devcaps(WORD dev_id, MIDIINCAPSW *caps, UINT size)
return MMSYSERR_NOERROR;
}
+static DWORD midi_in_reset(WORD dev_id, struct notify_context *notify)
+{
+ UINT cur_time = NtGetTickCount();
+ UINT err = MMSYSERR_NOERROR;
+ struct midi_src *src;
+ MIDIHDR *hdr;
+
+ TRACE("(%04X);\n", dev_id);
+
+ if (dev_id >= num_srcs) return MMSYSERR_BADDEVICEID;
+ src = srcs + dev_id;
+ if (src->state == -1) return MIDIERR_NODEVICE;
+
+ in_buffer_lock();
+
+ if (src->lpQueueHdr)
+ {
+ hdr = src->lpQueueHdr;
+ src->lpQueueHdr = hdr->lpNext;
+ hdr->dwFlags &= ~MHDR_INQUEUE;
+ hdr->dwFlags |= MHDR_DONE;
+ set_in_notify(notify, src, dev_id, MIM_LONGDATA, (DWORD_PTR)hdr, cur_time - src->startTime);
+ if (src->lpQueueHdr) err = ERROR_RETRY; /* ask the client to call again */
+ }
+
+ in_buffer_unlock();
+
+ return err;
+}
+
NTSTATUS midi_out_message(void *args)
{
struct midi_out_message_params *params = args;
@@ -987,6 +1031,8 @@ NTSTATUS midi_in_message(void *args)
{
struct midi_in_message_params *params = args;
+ params->notify->send_notify = FALSE;
+
switch (params->msg)
{
case DRVM_EXIT:
@@ -1010,6 +1056,9 @@ NTSTATUS midi_in_message(void *args)
case MIDM_GETNUMDEVS:
*params->err = num_srcs;
break;
+ case MIDM_RESET:
+ *params->err = midi_in_reset(params->dev_id, params->notify);
+ break;
default:
TRACE("Unsupported message\n");
*params->err = MMSYSERR_NOTSUPPORTED;
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index 72649eca89c..5639bf67369 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -459,31 +459,6 @@ static DWORD midClose(WORD wDevID)
return ret;
}
-/**************************************************************************
- * midReset [internal]
- */
-static DWORD midReset(WORD wDevID)
-{
- DWORD dwTime = GetTickCount();
-
- TRACE("(%04X);\n", wDevID);
-
- if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;
- if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;
-
- in_buffer_lock();
- while (MidiInDev[wDevID].lpQueueHdr) {
- LPMIDIHDR lpMidiHdr = MidiInDev[wDevID].lpQueueHdr;
- MidiInDev[wDevID].lpQueueHdr = lpMidiHdr->lpNext;
- lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
- lpMidiHdr->dwFlags |= MHDR_DONE;
- MIDI_NotifyClient(wDevID, MIM_LONGDATA, (DWORD_PTR)lpMidiHdr, dwTime - MidiInDev[wDevID].startTime);
- }
- in_buffer_unlock();
-
- return MMSYSERR_NOERROR;
-}
-
/**************************************************************************
* midStart [internal]
*/
@@ -545,6 +520,7 @@ DWORD WINAPI ALSA_midMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
struct midi_in_message_params params;
+ struct notify_context notify;
UINT err;
TRACE("(%04X, %04X, %08lX, %08lX, %08lX);\n",
@@ -557,8 +533,6 @@ DWORD WINAPI ALSA_midMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
return midOpen(wDevID, (LPMIDIOPENDESC)dwParam1, dwParam2);
case MIDM_CLOSE:
return midClose(wDevID);
- case MIDM_RESET:
- return midReset(wDevID);
case MIDM_START:
return midStart(wDevID);
case MIDM_STOP:
@@ -571,8 +545,13 @@ DWORD WINAPI ALSA_midMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
params.param_1 = dwParam1;
params.param_2 = dwParam2;
params.err = &err;
+ params.notify = ¬ify;
- ALSA_CALL(midi_in_message, ¶ms);
+ do
+ {
+ ALSA_CALL(midi_in_message, ¶ms);
+ if ((!err || err == ERROR_RETRY) && notify.send_notify) notify_client(¬ify);
+ } while (err == ERROR_RETRY);
return err;
}
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
index 263e83eda57..6d5bcb64cf0 100644
--- a/dlls/winealsa.drv/unixlib.h
+++ b/dlls/winealsa.drv/unixlib.h
@@ -262,6 +262,7 @@ struct midi_in_message_params
UINT_PTR param_1;
UINT_PTR param_2;
UINT *err;
+ struct notify_context *notify;
};
struct midi_seq_open_params
--
2.25.1
2
1