Rebase against 65797763b3ac4fcab7ffc83a4f95b2e87c81f58a.

This commit is contained in:
Alistair Leslie-Hughes 2022-10-25 11:22:47 +11:00
parent 1f500db5b7
commit 8703ad8375
13 changed files with 192 additions and 546 deletions

View File

@ -1,21 +1,19 @@
From 8919be537a3ada49b59f2686cc14dbfb81a37cb1 Mon Sep 17 00:00:00 2001
From 5a529bea97ee22d51f07f9d3cd77c00ea5292878 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 16 Jan 2014 20:56:49 -0700
Subject: ntdll: Add support for creating reparse points.
Subject: [PATCH] ntdll: Add support for creating reparse points.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
configure.ac | 2 +
dlls/ntdll/Makefile.in | 2 +-
dlls/ntdll/tests/file.c | 152 ++++++++++++++++++++
dlls/ntdll/tests/file.c | 159 ++++++++++++++++++---
dlls/ntdll/unix/file.c | 302 ++++++++++++++++++++++++++++++++++++++++
include/Makefile.in | 1 +
include/ntifs.h | 42 ++++++
6 files changed, 500 insertions(+), 1 deletion(-)
create mode 100644 include/ntifs.h
5 files changed, 447 insertions(+), 19 deletions(-)
diff --git a/configure.ac b/configure.ac
index e11f3cfdb63..113d126a002 100644
index 628cce28815..2adf40c0ef1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2018,6 +2018,8 @@ AC_CHECK_FUNCS(\
@ -41,7 +39,7 @@ index 3b1cdb54f9f..6eb4690f8e0 100644
EXTRADLLFLAGS = -nodefaultlibs -Wl,--image-base,0x7bc00000
x86_64_EXTRADLLFLAGS = -nodefaultlibs -Wl,--image-base,0x170000000
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index c011733626f..93e50bd6952 100644
index 98d9e6b3b0a..93e50bd6952 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -38,6 +38,7 @@
@ -52,7 +50,7 @@ index c011733626f..93e50bd6952 100644
#ifndef IO_COMPLETION_ALL_ACCESS
#define IO_COMPLETION_ALL_ACCESS 0x001F0003
@@ -5326,6 +5327,156 @@ static void test_mailslot_name(void)
@@ -5326,32 +5327,154 @@ static void test_mailslot_name(void)
CloseHandle( device );
}
@ -82,8 +80,12 @@ index c011733626f..93e50bd6952 100644
+ return buffer_size;
+}
+
+static void test_reparse_points(void)
+{
static void test_reparse_points(void)
{
- OBJECT_ATTRIBUTES attr;
- HANDLE handle;
- IO_STATUS_BLOCK io;
- NTSTATUS status;
+ WCHAR path[MAX_PATH], reparse_path[MAX_PATH], target_path[MAX_PATH], volnameW[MAX_PATH];
+ static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0};
+ static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
@ -93,7 +95,8 @@ index c011733626f..93e50bd6952 100644
+ static const WCHAR dotW[] = {'.',0};
+ REPARSE_DATA_BUFFER *buffer = NULL;
+ DWORD dwret, dwLen, dwFlags;
+ UNICODE_STRING nameW;
UNICODE_STRING nameW;
- unsigned char reparse_data[1];
+ WCHAR *long_path;
+ INT buffer_len;
+ HANDLE handle;
@ -130,7 +133,9 @@ index c011733626f..93e50bd6952 100644
+ lstrcatW(reparse_path, reparseW);
+ bret = CreateDirectoryW(reparse_path, NULL);
+ ok(bret, "Failed to create junction point directory.\n");
+
- pRtlInitUnicodeString( &nameW, L"\\??\\C:\\" );
- InitializeObjectAttributes( &attr, &nameW, 0, NULL, NULL );
+ /* Create a destination folder for the junction point to target */
+ lstrcpyW(target_path, path);
+ for (int i=0; i<1; i++)
@ -142,7 +147,9 @@ index c011733626f..93e50bd6952 100644
+ bret = CreateDirectoryW(target_path, NULL);
+ ok(bret, "Failed to create junction point target directory.\n");
+ pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
+
- status = pNtOpenFile( &handle, READ_CONTROL, &attr, &io, 0, 0 );
- ok( !status, "open %s failed %#lx\n", wine_dbgstr_w(nameW.Buffer), status );
+ /* construct a too long pathname (resulting reparse buffer over 16 kiB limit) */
+ long_path = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 32767);
+ lstrcpyW(long_path, nameW.Buffer);
@ -166,7 +173,9 @@ index c011733626f..93e50bd6952 100644
+ ok(!bret && GetLastError()==ERROR_INVALID_REPARSE_DATA, "Unexpected error (0x%lx)\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, buffer);
+ CloseHandle(handle);
+
- status = pNtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_GET_REPARSE_POINT, NULL, 0, NULL, 0 );
- ok( status == STATUS_INVALID_USER_BUFFER, "expected %#lx, got %#lx\n", STATUS_INVALID_USER_BUFFER, status );
+ /* construct a long pathname to demonstrate correct behavior with very large reparse points */
+ pRtlDosPathNameToNtPathName_U(path, &nameW, NULL, NULL);
+ lstrcpyW(long_path, nameW.Buffer);
@ -176,11 +185,16 @@ index c011733626f..93e50bd6952 100644
+ lstrcatW(long_path, path);
+ }
+ lstrcatW(long_path, targetW);
+
- status = pNtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse_data, 0 );
- ok( status == STATUS_INVALID_USER_BUFFER, "expected %#lx, got %#lx\n", STATUS_INVALID_USER_BUFFER, status );
+ /* use a sane (not obscenely long) target for the rest of testing */
+ pRtlFreeUnicodeString(&nameW);
+ pRtlDosPathNameToNtPathName_U(target_path, &nameW, NULL, NULL);
+
- /* a volume cannot be a reparse point by definition */
- status = pNtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse_data, 1 );
- ok( status == STATUS_NOT_A_REPARSE_POINT, "expected %#lx, got %#lx\n", STATUS_NOT_A_REPARSE_POINT, status );
+ /* Create the junction point */
+ handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0);
@ -193,7 +207,8 @@ index c011733626f..93e50bd6952 100644
+ bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
+ ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
+ CloseHandle(handle);
+
- CloseHandle( handle );
+cleanup:
+ /* Cleanup */
+ pRtlFreeUnicodeString(&nameW);
@ -204,20 +219,19 @@ index c011733626f..93e50bd6952 100644
+ bret = RemoveDirectoryW(target_path);
+ ok(bret, "Failed to remove temporary target directory!\n");
+ RemoveDirectoryW(path);
+}
+
}
START_TEST(file)
{
HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
@@ -5398,5 +5549,6 @@ START_TEST(file)
@@ -5426,6 +5549,6 @@ START_TEST(file)
test_ioctl();
test_query_ea();
test_flush_buffers_file();
+ test_reparse_points();
test_mailslot_name();
- test_mailslot_name();
test_reparse_points();
+ test_mailslot_name();
}
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 604ca866890..f3d831b0a33 100644
index 6b73d9dc7e8..52b85cfc6d1 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -36,6 +36,8 @@
@ -375,7 +389,7 @@ index 604ca866890..f3d831b0a33 100644
static BOOL fd_is_mount_point( int fd, const struct stat *st )
{
struct stat parent;
@@ -3303,6 +3423,181 @@ done:
@@ -3313,6 +3433,181 @@ done:
}
@ -557,7 +571,7 @@ index 604ca866890..f3d831b0a33 100644
/******************************************************************************
* lookup_unix_name
*
@@ -6052,6 +6347,13 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
@@ -6072,6 +6367,13 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
break;
}
@ -583,54 +597,6 @@ index 1c04f9a298b..7a2c9f96c1b 100644
ntlsa.h \
ntquery.h \
ntsecapi.h \
diff --git a/include/ntifs.h b/include/ntifs.h
new file mode 100644
index 00000000000..21d42e17325
--- /dev/null
+++ b/include/ntifs.h
@@ -0,0 +1,42 @@
+/*
+ * Win32 definitions for Windows NT
+ *
+ * Copyright 2012 Erich E. Hoover
+ *
+ * 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_NTIFS_H
+#define __WINE_NTIFS_H
+
+typedef struct _REPARSE_DATA_BUFFER {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ };
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+
+#endif /* __WINE_NTIFS_H */
--
2.17.1
2.37.2

View File

@ -1,19 +1,19 @@
From 51f1d4cee59b11181bbf1432ef7c954020269cf3 Mon Sep 17 00:00:00 2001
From 801191c93bc6780ee726727c82c0e0b696e300ef Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 16 Jan 2014 20:57:57 -0700
Subject: ntdll: Add support for reading reparse points.
Subject: [PATCH] ntdll: Add support for reading reparse points.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
dlls/ntdll/tests/file.c | 21 +++-
dlls/ntdll/unix/file.c | 212 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 231 insertions(+), 2 deletions(-)
dlls/ntdll/unix/file.c | 222 ++++++++++++++++++++++++++++++++++++++--
2 files changed, 231 insertions(+), 12 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 93e50bd6952..805f5a6a940 100644
index 17da7552046..b9ec79e37e0 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5359,14 +5359,14 @@ static void test_reparse_points(void)
@@ -5387,14 +5387,14 @@ static void test_reparse_points(void)
static const WCHAR reparseW[] = {'\\','r','e','p','a','r','s','e',0};
static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
static const WCHAR parentW[] = {'\\','.','.','\\',0};
@ -30,7 +30,7 @@ index 93e50bd6952..805f5a6a940 100644
HANDLE handle;
BOOL bret;
@@ -5463,6 +5463,23 @@ static void test_reparse_points(void)
@@ -5491,6 +5491,23 @@ static void test_reparse_points(void)
buffer_len = build_reparse_buffer(long_path, &buffer);
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
@ -55,7 +55,7 @@ index 93e50bd6952..805f5a6a940 100644
cleanup:
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index f3d831b0a33..8fe543ded08 100644
index 52b85cfc6d1..0967b3b9392 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -315,6 +315,84 @@ static UINT encode_base64url( const char *bin, unsigned int len, char *base64 )
@ -143,7 +143,7 @@ index f3d831b0a33..8fe543ded08 100644
/* create a directory and all the needed parent directories */
static int mkdir_p( int dirfd, const char *path, mode_t mode )
{
@@ -3598,6 +3676,132 @@ cleanup:
@@ -3608,6 +3686,132 @@ cleanup:
}
@ -276,7 +276,24 @@ index f3d831b0a33..8fe543ded08 100644
/******************************************************************************
* lookup_unix_name
*
@@ -6347,6 +6551,14 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
@@ -6335,16 +6539,6 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
break;
}
- case FSCTL_GET_REPARSE_POINT:
- io->Information = 0;
- if (out_buffer && out_size)
- {
- FIXME("FSCTL_GET_REPARSE_POINT semi-stub\n");
- status = STATUS_NOT_A_REPARSE_POINT;
- }
- else status = STATUS_INVALID_USER_BUFFER;
- break;
-
case FSCTL_GET_OBJECT_ID:
{
FILE_OBJECTID_BUFFER *info = out_buffer;
@@ -6367,6 +6561,14 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
break;
}
@ -292,5 +309,5 @@ index f3d831b0a33..8fe543ded08 100644
{
REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)in_buffer;
--
2.17.1
2.37.2

View File

@ -1,20 +1,19 @@
From cef94f0a808ceccbb756a3fea6622927aff4e489 Mon Sep 17 00:00:00 2001
From 3c25b2e7839c1493f97d144f137822cbf9a498a3 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 16 Jan 2014 21:00:21 -0700
Subject: ntdll: Add support for deleting reparse points.
Subject: [PATCH] ntdll: Add support for deleting reparse points.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
dlls/ntdll/tests/file.c | 23 +++++++++-
dlls/ntdll/unix/file.c | 99 +++++++++++++++++++++++++++++++++++++++++
include/ntifs.h | 12 +++++
3 files changed, 133 insertions(+), 1 deletion(-)
2 files changed, 121 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 805f5a6a940..a127a2f4f88 100644
index b9ec79e37e0..f90509d62a1 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5360,12 +5360,15 @@ static void test_reparse_points(void)
@@ -5388,12 +5388,15 @@ static void test_reparse_points(void)
static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0};
static const WCHAR parentW[] = {'\\','.','.','\\',0};
INT buffer_len, string_len, path_len, total_len;
@ -30,7 +29,7 @@ index 805f5a6a940..a127a2f4f88 100644
UNICODE_STRING nameW;
HANDLE handle;
BOOL bret;
@@ -5460,6 +5463,8 @@ static void test_reparse_points(void)
@@ -5488,6 +5491,8 @@ static void test_reparse_points(void)
win_skip("Failed to open junction point directory handle (0x%lx).\n", GetLastError());
goto cleanup;
}
@ -39,7 +38,7 @@ index 805f5a6a940..a127a2f4f88 100644
buffer_len = build_reparse_buffer(long_path, &buffer);
bret = DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, (LPVOID)buffer, buffer_len, NULL, 0, &dwret, 0);
ok(bret, "Failed to create junction point! (0x%lx)\n", GetLastError());
@@ -5480,6 +5485,22 @@ static void test_reparse_points(void)
@@ -5508,6 +5513,22 @@ static void test_reparse_points(void)
- FIELD_OFFSET(typeof(*buffer), GenericReparseBuffer);
ok(buffer->ReparseDataLength == total_len, "ReparseDataLength has unexpected value (%d != %d)\n",
buffer->ReparseDataLength, total_len);
@ -62,7 +61,7 @@ index 805f5a6a940..a127a2f4f88 100644
CloseHandle(handle);
cleanup:
@@ -5488,7 +5509,7 @@ cleanup:
@@ -5516,7 +5537,7 @@ cleanup:
HeapFree(GetProcessHeap(), 0, long_path);
HeapFree(GetProcessHeap(), 0, buffer);
bret = RemoveDirectoryW(reparse_path);
@ -72,10 +71,10 @@ index 805f5a6a940..a127a2f4f88 100644
ok(bret, "Failed to remove temporary target directory!\n");
RemoveDirectoryW(path);
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 8fe543ded08..4c221f53bfd 100644
index 92ce83b685e..ba77aab61b7 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -3802,6 +3802,99 @@ cleanup:
@@ -3812,6 +3812,99 @@ cleanup:
}
@ -175,7 +174,7 @@ index 8fe543ded08..4c221f53bfd 100644
/******************************************************************************
* lookup_unix_name
*
@@ -6551,6 +6644,12 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
@@ -6571,6 +6664,12 @@ NTSTATUS WINAPI NtFsControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE ap
break;
}
@ -188,27 +187,6 @@ index 8fe543ded08..4c221f53bfd 100644
case FSCTL_GET_REPARSE_POINT:
{
REPARSE_DATA_BUFFER *buffer = (REPARSE_DATA_BUFFER *)out_buffer;
diff --git a/include/ntifs.h b/include/ntifs.h
index 21d42e17325..4539b89d583 100644
--- a/include/ntifs.h
+++ b/include/ntifs.h
@@ -39,4 +39,16 @@ typedef struct _REPARSE_DATA_BUFFER {
};
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+typedef struct _REPARSE_GUID_DATA_BUFFER {
+ DWORD ReparseTag;
+ WORD ReparseDataLength;
+ WORD Reserved;
+ GUID ReparseGuid;
+ struct {
+ BYTE DataBuffer[1];
+ } GenericReparseBuffer;
+} REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;
+
+#define REPARSE_GUID_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer)
+
#endif /* __WINE_NTIFS_H */
--
2.17.1
2.37.2

View File

@ -1,13 +1,12 @@
From d636805ef7d44cf78a08538f3c6c2e8f5a2f0d87 Mon Sep 17 00:00:00 2001
From caaa38a56b7bb5e81bb71f5a6c3489755ebaee98 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
Date: Sat, 6 Feb 2021 12:52:51 -0700
Subject: ntdll: Add tests for NT symlink reparse points.
Subject: [PATCH] ntdll: Add tests for NT symlink reparse points.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
dlls/ntdll/tests/file.c | 239 +++++++++++++++++++++++++++++++++++++---
include/ntifs.h | 12 ++
2 files changed, 237 insertions(+), 14 deletions(-)
1 file changed, 225 insertions(+), 14 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 4e3f0f04a3e..48abcd338bb 100644
@ -319,46 +318,6 @@ index 4e3f0f04a3e..48abcd338bb 100644
cleanup:
/* Cleanup */
pRtlFreeUnicodeString(&nameW);
diff --git a/include/ntifs.h b/include/ntifs.h
index 4539b89d583..0d02225bc4f 100644
--- a/include/ntifs.h
+++ b/include/ntifs.h
@@ -21,11 +21,20 @@
#ifndef __WINE_NTIFS_H
#define __WINE_NTIFS_H
+#include <pshpack2.h>
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
@@ -38,6 +47,7 @@ typedef struct _REPARSE_DATA_BUFFER {
} GenericReparseBuffer;
};
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+#include <poppack.h>
typedef struct _REPARSE_GUID_DATA_BUFFER {
DWORD ReparseTag;
@@ -51,4 +61,6 @@ typedef struct _REPARSE_GUID_DATA_BUFFER {
#define REPARSE_GUID_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer)
+#define SYMLINK_FLAG_RELATIVE 0x00000001
+
#endif /* __WINE_NTIFS_H */
--
2.17.1
2.37.2

View File

@ -1,21 +1,20 @@
From 57de4a076b99117d523349f168194c7334219303 Mon Sep 17 00:00:00 2001
From e4b0e1bd0ae993ac209367318a98ad63a5eec62b Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@wine-staging.com>
Date: Mon, 3 May 2021 09:28:08 -0600
Subject: ntdll: Add support for creating Unix/Linux symlinks.
Subject: [PATCH] ntdll: Add support for creating Unix/Linux symlinks.
Signed-off-by: Erich E. Hoover <erich.e.hoover@gmail.com>
---
dlls/ntdll/tests/file.c | 35 +++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/file.c | 38 ++++++++++++++++++++++++++------------
include/ntifs.h | 4 ++++
include/winnt.h | 1 +
4 files changed, 66 insertions(+), 12 deletions(-)
3 files changed, 62 insertions(+), 12 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 2450e9e5b4a..16a45636ebe 100644
index 2139ddd8ea2..fc08a533559 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -5398,6 +5398,8 @@ static void test_reparse_points(void)
@@ -5426,6 +5426,8 @@ static void test_reparse_points(void)
REPARSE_DATA_BUFFER *buffer = NULL;
DWORD dwret, dwLen, dwFlags, err;
WIN32_FILE_ATTRIBUTE_DATA fad;
@ -24,7 +23,7 @@ index 2450e9e5b4a..16a45636ebe 100644
WCHAR buf[] = {0,0,0,0};
HANDLE handle, token;
IO_STATUS_BLOCK iosb;
@@ -5762,6 +5764,39 @@ static void test_reparse_points(void)
@@ -5790,6 +5792,39 @@ static void test_reparse_points(void)
"Symlink folder's access time does not match.\n");
CloseHandle(handle);
@ -65,10 +64,10 @@ index 2450e9e5b4a..16a45636ebe 100644
HeapFree(GetProcessHeap(), 0, buffer);
handle = CreateFileW(reparse_path, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index 51d6aed85f0..b17ee58d736 100644
index fe1c50468a4..f87117438b8 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -3751,20 +3751,33 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -3761,20 +3761,33 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
* *) Append the base64-url encoded reparse point buffer
* *) Append the filename of the first continuing symlink (0) in case we need it
*/
@ -113,7 +112,7 @@ index 51d6aed85f0..b17ee58d736 100644
/* Produce the link in a temporary location in the same folder */
strcpy( tmpdir, unix_src );
@@ -3829,7 +3842,8 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
@@ -3839,7 +3852,8 @@ NTSTATUS create_reparse_point(HANDLE handle, REPARSE_DATA_BUFFER *buffer)
}
/* create the very last link directory */
@ -123,26 +122,11 @@ index 51d6aed85f0..b17ee58d736 100644
{
strcpy( link_path, target_path );
strcpy( link_dir, link_path );
diff --git a/include/ntifs.h b/include/ntifs.h
index 0d02225bc4f..25af12a413a 100644
--- a/include/ntifs.h
+++ b/include/ntifs.h
@@ -42,6 +42,10 @@ typedef struct _REPARSE_DATA_BUFFER {
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
+ struct {
+ ULONG Version;
+ UCHAR PathBuffer[1];
+ } LinuxSymbolicLinkReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
diff --git a/include/winnt.h b/include/winnt.h
index 19bb5be83c4..ff4e502d65b 100644
index 019d0b16693..469287cc0ef 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -2324,6 +2324,7 @@ extern struct _TEB * WINAPI NtCurrentTeb(void);
@@ -2330,6 +2330,7 @@ extern struct _TEB * WINAPI NtCurrentTeb(void);
#define IO_REPARSE_TAG_CLOUD_MASK __MSABI_LONG(0x0000F000)
#define IO_REPARSE_TAG_APPEXECLINK __MSABI_LONG(0x8000001B)
#define IO_REPARSE_TAG_GVFS __MSABI_LONG(0x9000001C)
@ -151,5 +135,5 @@ index 19bb5be83c4..ff4e502d65b 100644
#define IO_REPARSE_TAG_WCI_TOMBSTONE __MSABI_LONG(0xA000001F)
#define IO_REPARSE_TAG_UNHANDLED __MSABI_LONG(0x80000020)
--
2.17.1
2.37.2

View File

@ -0,0 +1,90 @@
From efbadece6648c4164d5e24070cb8aa2cb2440cc4 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Tue, 25 Oct 2022 11:26:04 +1100
Subject: [PATCH] include: Add ntifs.h
Moved here since I forgot to add it during a rebase.
---
include/ntifs.h | 70 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
create mode 100644 include/ntifs.h
diff --git a/include/ntifs.h b/include/ntifs.h
new file mode 100644
index 00000000000..25af12a413a
--- /dev/null
+++ b/include/ntifs.h
@@ -0,0 +1,70 @@
+/*
+ * Win32 definitions for Windows NT
+ *
+ * Copyright 2012 Erich E. Hoover
+ *
+ * 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_NTIFS_H
+#define __WINE_NTIFS_H
+
+#include <pshpack2.h>
+typedef struct _REPARSE_DATA_BUFFER {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct {
+ ULONG Version;
+ UCHAR PathBuffer[1];
+ } LinuxSymbolicLinkReparseBuffer;
+ struct {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ };
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+#include <poppack.h>
+
+typedef struct _REPARSE_GUID_DATA_BUFFER {
+ DWORD ReparseTag;
+ WORD ReparseDataLength;
+ WORD Reserved;
+ GUID ReparseGuid;
+ struct {
+ BYTE DataBuffer[1];
+ } GenericReparseBuffer;
+} REPARSE_GUID_DATA_BUFFER, *PREPARSE_GUID_DATA_BUFFER;
+
+#define REPARSE_GUID_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_GUID_DATA_BUFFER, GenericReparseBuffer)
+
+#define SYMLINK_FLAG_RELATIVE 0x00000001
+
+#endif /* __WINE_NTIFS_H */
--
2.37.2

View File

@ -51,7 +51,7 @@ usage()
# Get the upstream commit sha
upstream_commit()
{
echo "25b05840d4fad5d12f308077925e3cf92bcebfb7"
echo "65797763b3ac4fcab7ffc83a4f95b2e87c81f58a"
}
# Show version information
@ -161,7 +161,6 @@ patch_enable_all ()
enable_programs_systeminfo="$1"
enable_riched20_IText_Interface="$1"
enable_sapi_ISpObjectToken_CreateInstance="$1"
enable_sapi_iteration_tokens="$1"
enable_server_File_Permissions="$1"
enable_server_PeekMessage="$1"
enable_server_Realtime_Priority="$1"
@ -500,9 +499,6 @@ patch_enable ()
sapi-ISpObjectToken-CreateInstance)
enable_sapi_ISpObjectToken_CreateInstance="$2"
;;
sapi-iteration-tokens)
enable_sapi_iteration_tokens="$2"
;;
server-File_Permissions)
enable_server_File_Permissions="$2"
;;
@ -1209,13 +1205,6 @@ if test "$enable_server_File_Permissions" -eq 1; then
enable_ntdll_Junction_Points=1
fi
if test "$enable_sapi_iteration_tokens" -eq 1; then
if test "$enable_sapi_ISpObjectToken_CreateInstance" -gt 1; then
abort "Patchset sapi-ISpObjectToken-CreateInstance disabled, but sapi-iteration-tokens depends on that."
fi
enable_sapi_ISpObjectToken_CreateInstance=1
fi
if test "$enable_oleaut32_OLEPictureImpl_SaveAsFile" -eq 1; then
if test "$enable_oleaut32_Load_Save_EMF" -gt 1; then
abort "Patchset oleaut32-Load_Save_EMF disabled, but oleaut32-OLEPictureImpl_SaveAsFile depends on that."
@ -1709,6 +1698,7 @@ if test "$enable_ntdll_Junction_Points" -eq 1; then
patch_apply ntdll-Junction_Points/0023-wcmd-Add-junction-point-support-to-mklink.patch
patch_apply ntdll-Junction_Points/0024-ntdll-Add-support-for-creating-Unix-Linux-symlinks.patch
patch_apply ntdll-Junction_Points/0025-ntdll-Report-regular-Unix-symlinks-as-WSL-Linux-Unix.patch
patch_apply ntdll-Junction_Points/0026-include-Add-ntifs.h.patch
fi
# Patchset server-PeekMessage
@ -2515,24 +2505,6 @@ if test "$enable_sapi_ISpObjectToken_CreateInstance" -eq 1; then
patch_apply sapi-ISpObjectToken-CreateInstance/0004-sapi-ISpObjectToken-CreateInstance-support-ISpAudio.patch
fi
# Patchset sapi-iteration-tokens
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * sapi-ISpObjectToken-CreateInstance
# |
# | This patchset fixes the following Wine bugs:
# | * [#51775] sapi: Allow iteration of Token objects.
# |
# | Modified files:
# | * dlls/sapi/sapi.rgs, dlls/sapi/token.c
# |
if test "$enable_sapi_iteration_tokens" -eq 1; then
patch_apply sapi-iteration-tokens/0004-sapi-EnumTokens-setup-enumeration-members.patch
patch_apply sapi-iteration-tokens/0005-sapi-Implement-ISpObjectTokenEnumBuilder-Item.patch
patch_apply sapi-iteration-tokens/0008-sapi-Add-default-voice-registry-key.patch
patch_apply sapi-iteration-tokens/0009-sapi-Return-dump-object-in-ISpObjectTokenEnumBuilder.patch
fi
# Patchset server-File_Permissions
# |
# | This patchset has the following (direct or indirect) dependencies:

View File

@ -1,108 +0,0 @@
From 5326c101e7cd8f0d0197319fd0d7d652d845c20e Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Wed, 22 Sep 2021 19:01:44 +1000
Subject: [PATCH] sapi: EnumTokens setup enumeration members
---
dlls/sapi/token.c | 48 ++++++++++++++++++++++++++++++-----------------
1 file changed, 31 insertions(+), 17 deletions(-)
diff --git a/dlls/sapi/token.c b/dlls/sapi/token.c
index 853dc2fd21f..957ef77b41e 100644
--- a/dlls/sapi/token.c
+++ b/dlls/sapi/token.c
@@ -48,6 +48,22 @@ static struct data_key *impl_from_ISpRegDataKey( ISpRegDataKey *iface )
return CONTAINING_RECORD( iface, struct data_key, ISpRegDataKey_iface );
}
+struct token_enum
+{
+ ISpObjectTokenEnumBuilder ISpObjectTokenEnumBuilder_iface;
+ LONG ref;
+
+ BOOL init;
+ WCHAR *req, *opt;
+ ULONG count;
+ HKEY key;
+};
+
+static struct token_enum *impl_from_ISpObjectTokenEnumBuilder( ISpObjectTokenEnumBuilder *iface )
+{
+ return CONTAINING_RECORD( iface, struct token_enum, ISpObjectTokenEnumBuilder_iface );
+}
+
static HRESULT WINAPI data_key_QueryInterface( ISpRegDataKey *iface, REFIID iid, void **obj )
{
struct data_key *This = impl_from_ISpRegDataKey( iface );
@@ -503,9 +519,11 @@ static HRESULT WINAPI token_category_EnumTokens( ISpObjectTokenCategory *iface,
{
struct token_category *This = impl_from_ISpObjectTokenCategory( iface );
ISpObjectTokenEnumBuilder *builder;
+ struct token_enum *tokenenum;
+ struct data_key *this_data_key;
HRESULT hr;
- FIXME( "(%p)->(%s %s %p): semi-stub\n", This, debugstr_w( req ), debugstr_w( opt ), enum_tokens );
+ TRACE( "(%p)->(%s %s %p)\n", This, debugstr_w( req ), debugstr_w( opt ), enum_tokens );
if (!This->data_key) return SPERR_UNINITIALIZED;
@@ -516,7 +534,15 @@ static HRESULT WINAPI token_category_EnumTokens( ISpObjectTokenCategory *iface,
hr = ISpObjectTokenEnumBuilder_SetAttribs( builder, req, opt );
if (FAILED(hr)) goto fail;
- /* FIXME: Build the enumerator */
+ this_data_key = impl_from_ISpRegDataKey( This->data_key );
+
+ tokenenum = impl_from_ISpObjectTokenEnumBuilder( builder );
+
+ if(!RegOpenKeyExW( this_data_key->key, L"Tokens", 0, KEY_ALL_ACCESS, &tokenenum->key ))
+ {
+ RegQueryInfoKeyW(tokenenum->key, NULL, NULL, NULL, &tokenenum->count, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ }
hr = ISpObjectTokenEnumBuilder_QueryInterface( builder, &IID_IEnumSpObjectTokens,
(void **)enum_tokens );
@@ -611,21 +637,6 @@ HRESULT token_category_create( IUnknown *outer, REFIID iid, void **obj )
return hr;
}
-struct token_enum
-{
- ISpObjectTokenEnumBuilder ISpObjectTokenEnumBuilder_iface;
- LONG ref;
-
- BOOL init;
- WCHAR *req, *opt;
- ULONG count;
-};
-
-static struct token_enum *impl_from_ISpObjectTokenEnumBuilder( ISpObjectTokenEnumBuilder *iface )
-{
- return CONTAINING_RECORD( iface, struct token_enum, ISpObjectTokenEnumBuilder_iface );
-}
-
static HRESULT WINAPI token_enum_QueryInterface( ISpObjectTokenEnumBuilder *iface,
REFIID iid, void **obj )
{
@@ -665,6 +676,8 @@ static ULONG WINAPI token_enum_Release( ISpObjectTokenEnumBuilder *iface )
if (!ref)
{
+ if (This->key)
+ RegCloseKey(This->key);
heap_free( This->req );
heap_free( This->opt );
heap_free( This );
@@ -817,6 +830,7 @@ HRESULT token_enum_create( IUnknown *outer, REFIID iid, void **obj )
This->opt = NULL;
This->init = FALSE;
This->count = 0;
+ This->key = NULL;
hr = ISpObjectTokenEnumBuilder_QueryInterface( &This->ISpObjectTokenEnumBuilder_iface, iid, obj );
--
2.35.1

View File

@ -1,106 +0,0 @@
From 8e0713bfe03d37f19c2645a67b05024a86df0af8 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Wed, 22 Sep 2021 19:01:44 +1000
Subject: [PATCH] sapi: Implement ISpObjectTokenEnumBuilder Item
---
dlls/sapi/token.c | 69 ++++++++++++++++++++++++++++++++++++-----------
1 file changed, 53 insertions(+), 16 deletions(-)
diff --git a/dlls/sapi/token.c b/dlls/sapi/token.c
index c16572ff1f2..eb6d746cb04 100644
--- a/dlls/sapi/token.c
+++ b/dlls/sapi/token.c
@@ -64,6 +64,20 @@ static struct token_enum *impl_from_ISpObjectTokenEnumBuilder( ISpObjectTokenEnu
return CONTAINING_RECORD( iface, struct token_enum, ISpObjectTokenEnumBuilder_iface );
}
+struct object_token
+{
+ ISpObjectToken ISpObjectToken_iface;
+ LONG ref;
+
+ HKEY token_key;
+ WCHAR *token_id;
+};
+
+static struct object_token *impl_from_ISpObjectToken( ISpObjectToken *iface )
+{
+ return CONTAINING_RECORD( iface, struct object_token, ISpObjectToken_iface );
+}
+
static HRESULT WINAPI data_key_QueryInterface( ISpRegDataKey *iface, REFIID iid, void **obj )
{
struct data_key *This = impl_from_ISpRegDataKey( iface );
@@ -725,8 +739,45 @@ static HRESULT WINAPI token_enum_Clone( ISpObjectTokenEnumBuilder *iface,
static HRESULT WINAPI token_enum_Item( ISpObjectTokenEnumBuilder *iface,
ULONG index, ISpObjectToken **token )
{
- FIXME( "stub\n" );
- return E_NOTIMPL;
+ struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface );
+ struct object_token *object;
+ ISpObjectToken *subtoken;
+ HRESULT hr;
+ WCHAR *subkey;
+ DWORD size;
+ LONG ret;
+ HKEY key;
+
+ TRACE( "%p, %d, %p\n", This, index, token );
+
+ if (!This->init)
+ return SPERR_UNINITIALIZED;
+
+ RegQueryInfoKeyW(This->key, NULL, NULL, NULL, NULL, &size, NULL, NULL, NULL, NULL, NULL, NULL);
+ size = (size+1) * sizeof(WCHAR);
+ subkey = heap_alloc(size);
+ if (!subkey)
+ return E_OUTOFMEMORY;
+
+ ret = RegEnumKeyExW(This->key, index, subkey, &size, NULL, NULL, NULL, NULL);
+ if (ret != ERROR_SUCCESS)
+ return HRESULT_FROM_WIN32(ret);
+
+ ret = RegOpenKeyExW (This->key, subkey, 0, KEY_READ, &key);
+ if (ret != ERROR_SUCCESS)
+ return HRESULT_FROM_WIN32(ret);
+ heap_free(subkey);
+
+ hr = token_create( NULL, &IID_ISpObjectToken, (void**)&subtoken );
+ if (FAILED(hr))
+ return hr;
+
+ object = impl_from_ISpObjectToken( subtoken );
+ object->token_key = key;
+
+ *token = subtoken;
+
+ return hr;
}
static HRESULT WINAPI token_enum_GetCount( ISpObjectTokenEnumBuilder *iface,
@@ -838,20 +889,6 @@ HRESULT token_enum_create( IUnknown *outer, REFIID iid, void **obj )
return hr;
}
-struct object_token
-{
- ISpObjectToken ISpObjectToken_iface;
- LONG ref;
-
- HKEY token_key;
- WCHAR *token_id;
-};
-
-static struct object_token *impl_from_ISpObjectToken( ISpObjectToken *iface )
-{
- return CONTAINING_RECORD( iface, struct object_token, ISpObjectToken_iface );
-}
-
static HRESULT WINAPI token_QueryInterface( ISpObjectToken *iface,
REFIID iid, void **obj )
{
--
2.35.1

View File

@ -1,30 +0,0 @@
From 7c650212c2e33820d9436875c6987fca3579151c Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Wed, 22 Sep 2021 19:01:44 +1000
Subject: [PATCH 8/8] sapi: Add default voice registry key
---
dlls/sapi/sapi.rgs | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/dlls/sapi/sapi.rgs b/dlls/sapi/sapi.rgs
index 331e115ae71..33b720784cd 100644
--- a/dlls/sapi/sapi.rgs
+++ b/dlls/sapi/sapi.rgs
@@ -19,6 +19,13 @@ HKLM
}
NoRemove Voices
{
+ NoRemove Tokens
+ {
+ NoRemove 'Wine Default Voice'
+ {
+ NoRemove Attributes
+ }
+ }
}
}
}
--
2.33.0

View File

@ -1,74 +0,0 @@
From dad59a707bbb8a8d7be8132743f47465f235c929 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Tue, 28 Sep 2021 14:41:16 +1000
Subject: [PATCH] sapi: Return dump object in ISpObjectTokenEnumBuilder Next
---
dlls/sapi/token.c | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/dlls/sapi/token.c b/dlls/sapi/token.c
index c9c17a58589..55194feab22 100644
--- a/dlls/sapi/token.c
+++ b/dlls/sapi/token.c
@@ -57,6 +57,7 @@ struct token_enum
WCHAR *req, *opt;
ULONG count;
HKEY key;
+ DWORD index;
};
static struct token_enum *impl_from_ISpObjectTokenEnumBuilder( ISpObjectTokenEnumBuilder *iface )
@@ -705,6 +706,12 @@ static HRESULT WINAPI token_enum_Next( ISpObjectTokenEnumBuilder *iface,
ULONG *fetched )
{
struct token_enum *This = impl_from_ISpObjectTokenEnumBuilder( iface );
+ struct object_token *object;
+ HRESULT hr;
+ DWORD retCode;
+ WCHAR subKeyName[128];
+ DWORD size_sub = sizeof(subKeyName);
+ HKEY sub_key;
TRACE( "(%p)->(%lu %p %p)\n", This, num, tokens, fetched );
@@ -713,7 +720,27 @@ static HRESULT WINAPI token_enum_Next( ISpObjectTokenEnumBuilder *iface,
FIXME( "semi-stub: Returning an empty enumerator\n" );
if (fetched) *fetched = 0;
- return S_FALSE;
+ *tokens = NULL;
+
+ retCode = RegEnumKeyExW(This->key, This->index, subKeyName, &size_sub, NULL, NULL, NULL, NULL);
+ if (retCode != ERROR_SUCCESS)
+ return S_FALSE;
+
+ This->index++;
+
+ if( RegOpenKeyExW( This->key, subKeyName, 0, KEY_READ, &sub_key ) != ERROR_SUCCESS )
+ return E_FAIL;
+
+ hr = token_create( NULL, &IID_ISpObjectToken, (void**)tokens );
+ if (FAILED(hr))
+ return hr;
+
+ object = impl_from_ISpObjectToken( *tokens );
+ object->token_key = sub_key;
+ object->token_id = heap_strdupW( subKeyName );
+
+ if (fetched) *fetched = 1;
+ return hr;
}
static HRESULT WINAPI token_enum_Skip( ISpObjectTokenEnumBuilder *iface,
@@ -882,6 +909,7 @@ HRESULT token_enum_create( IUnknown *outer, REFIID iid, void **obj )
This->init = FALSE;
This->count = 0;
This->key = NULL;
+ This->index = 0;
hr = ISpObjectTokenEnumBuilder_QueryInterface( &This->ISpObjectTokenEnumBuilder_iface, iid, obj );
--
2.35.1

View File

@ -1,2 +0,0 @@
Fixes: [51775] sapi: Allow iteration of Token objects.
Depends: sapi-ISpObjectToken-CreateInstance

View File

@ -1 +1 @@
e72a16b57f66b63a16bb3d1619ac4d42632cb141
65797763b3ac4fcab7ffc83a4f95b2e87c81f58a